package com.canoo.cog.solver; /* * #%L * code-of-gotham * %% * Copyright (C) 2015 Canoo Engineering AG * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import javafx.geometry.BoundingBox; import javafx.geometry.Point2D; import javafx.geometry.Point3D; public class OptimumSolver implements Solver { private int streetSize; @Override public String toString() { return "Optimum Solver"; } @Override public void solveProblem(CityNode node, int streetSize) { this.streetSize = streetSize; if (node.isLeaf()) { return; } for (CityNode childNode : node.getChildren()) { solveProblem(childNode, streetSize); } doLayout(node, streetSize); } public void doLayout(CityNode parentNode, int streetSize) { Point3D nextEdgeZ = new Point3D(0d, 0d, 0d); Point3D nextEdgeX = new Point3D(0d, 0d, 0d); Point3D nextFreeXonZAxis = new Point3D(0d, 0d, 0d); Point3D nextFreeZonXAxis = new Point3D(0d, 0d, 0d); for (CityNode childNode : parentNode.getChildren()) { double nodeX = 0d; double nodeZ = 0d; double childSize = childNode.getSize() + streetSize; boolean needsResetXAxis = needsResetXAxis(nextEdgeX, nextFreeXonZAxis, childNode); boolean needsResetZAxis = needsResetZAxis(nextEdgeZ, nextFreeZonXAxis, childNode); boolean nextFreeXPointsIntersect = intersects(nextFreeXonZAxis, nextFreeZonXAxis, childSize); boolean nextEdgeXSmallerThanNextEdgeZ = nextEdgeX.getX() < nextEdgeZ.getZ(); if (!needsResetXAxis) { nodeX = nextFreeXonZAxis.getX(); nodeZ = nextFreeXonZAxis.getZ(); boolean needsResetZAxisXContext = needsResetZAxis(nextEdgeZ, nextFreeXonZAxis, childNode); if (needsResetZAxisXContext) { nextEdgeZ = nextEdgeZ.add(0d, 0d, childSize); } nextFreeXonZAxis = nextFreeXonZAxis.add(childSize, 0d, 0d); } else if (!needsResetZAxis && !nextFreeXPointsIntersect) { nodeX = nextFreeZonXAxis.getX(); nodeZ = nextFreeZonXAxis.getZ(); boolean needsResetXAxisZContext = needsResetXAxis(nextEdgeX, nextFreeZonXAxis, childNode); if (needsResetXAxisZContext) { nextEdgeX = nextEdgeX.add(childSize, 0d, 0d); } nextFreeZonXAxis = nextFreeZonXAxis.add(0d, 0d, childSize); } else { if (nextEdgeXSmallerThanNextEdgeZ) { nodeX = nextEdgeX.getX(); } else { nodeZ = nextEdgeZ.getZ(); } if (nextFreeXPointsIntersect && nextEdgeXSmallerThanNextEdgeZ) { nextFreeZonXAxis = new Point3D(nextEdgeX.getX(), nextEdgeX.getY(), nextEdgeX.getZ()); nextFreeZonXAxis = nextFreeZonXAxis.add(0d, 0d, childSize); nextEdgeX = nextEdgeX.add(childSize, 0d, 0d); } else if (needsResetXAxis) { nextEdgeX = nextEdgeX.add(childSize, 0d, 0d); nextFreeZonXAxis = new Point3D(nextEdgeX.getX(), nextEdgeX.getY(), nextEdgeX.getZ()); } if (needsResetZAxis) { nextEdgeZ = nextEdgeZ.add(0d, 0d, childSize); nextFreeXonZAxis = new Point3D(nextEdgeZ.getX(), nextEdgeZ.getY(), nextEdgeZ.getZ()); } else if (nextFreeXPointsIntersect && !nextEdgeXSmallerThanNextEdgeZ) { nextFreeXonZAxis = new Point3D(nextEdgeZ.getX(), nextEdgeZ.getY(), nextEdgeZ.getZ()); nextFreeXonZAxis = nextFreeXonZAxis.add(childSize, 0d, 0d); nextEdgeZ = nextEdgeZ.add(0d, 0d, childSize); } } int parentSize = parentNode.getSize(); childNode.setX((int) (childSize / 2 - parentSize / 2 + nodeX)); childNode.setY((int) (-childSize / 2 + parentSize / 2 - nodeZ)); } } private boolean needsResetXAxis(Point3D nextEdge, Point3D nextFreeOnAxis, CityNode child) { return nextEdge.getX() - nextFreeOnAxis.getX() < child.getSize() + streetSize; } private boolean needsResetZAxis(Point3D nextEdge, Point3D nextFreeOnAxis, CityNode child) { return nextEdge.getZ() - nextFreeOnAxis.getZ() < child.getSize() + streetSize; } private boolean intersects(Point3D checkPoint, Point3D childStartPoint, double childSize) { BoundingBox boundingBox = new BoundingBox(childStartPoint.getX(), childStartPoint.getZ(), childSize, childSize); Point2D checkPoint2D = new Point2D(checkPoint.getX(), checkPoint.getZ()); return boundingBox.contains(checkPoint2D); } }