X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.district.network.ui%2Fsrc%2Forg%2Fsimantics%2Fdistrict%2Fnetwork%2Fui%2Fnodes%2FDistrictNetworkNodeUtils.java;fp=org.simantics.district.network.ui%2Fsrc%2Forg%2Fsimantics%2Fdistrict%2Fnetwork%2Fui%2Fnodes%2FDistrictNetworkNodeUtils.java;h=2cc0ee96ae4ffa89ad97b696c3661944f13146bc;hb=7ebf5a4d72468b19d55cb79c0494d0538081d2ff;hp=0efab43173f112d4521667f4af00919434c3f7d2;hpb=290f621728aa09db5a719f9e7a29d4e342d25425;p=simantics%2Fdistrict.git diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkNodeUtils.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkNodeUtils.java index 0efab431..2cc0ee96 100644 --- a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkNodeUtils.java +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkNodeUtils.java @@ -1,6 +1,8 @@ package org.simantics.district.network.ui.nodes; import java.awt.geom.AffineTransform; +import java.awt.geom.Path2D; +import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; @@ -8,6 +10,8 @@ import org.simantics.district.network.ModelledCRS; import org.simantics.maps.MapScalingTransform; import org.simantics.scenegraph.utils.GeometryUtils; +import gnu.trove.list.array.TDoubleArrayList; + public class DistrictNetworkNodeUtils { public static ThreadLocal sharedTransform = new ThreadLocal() { @@ -54,4 +58,69 @@ public class DistrictNetworkNodeUtils { scale = Math.max(4096, scale); //Math.min(scale, 32768)); return scale; } -} + + /** + * Finds the longest line segment from the provided path and sets + * centerPoint to the middle of that line and + * direction as the normalized direction vector of that line + * segment. + * + *

+ * If the path has no points, both centerPoint and + * direction are set to ({@link Double#NaN}, {@link Double#NaN}). + * If the path has only one point then centerPoint is set to that + * single point and direction is set to (1,0). + * + * @param path the path to process + * @param centerPoint point for writing the output center point + * @param direction point for writing the output direction vector + * @return the amount of points in the path + */ + public static int calculateCenterPointAndDirection(Path2D path, Point2D centerPoint, Point2D direction) { + PathIterator pi = path.getPathIterator(null); + TDoubleArrayList segments = new TDoubleArrayList(20); + double[] tmp = new double[6]; + while (!pi.isDone()) { + pi.currentSegment(tmp); + segments.add(tmp[0]); + segments.add(tmp[1]); + pi.next(); + } + + // Cover corner cases + int segCount = segments.size(); + if (segCount == 0) { + centerPoint.setLocation(Double.NaN, Double.NaN); + direction.setLocation(Double.NaN, Double.NaN); + return 0; + } else if (segCount == 2) { + centerPoint.setLocation(segments.getQuick(0), segments.getQuick(1)); + direction.setLocation(1, 0); + return 1; + } + + int longest = 1; + double distance = 0.0; + for (int i = 2; i < segCount; i += 2) { + double dx = segments.getQuick(i) - segments.getQuick(i-2); + double dy = segments.getQuick(i+1) - segments.getQuick(i-1); + + double d = dx * dx + dy * dy; + if (d > distance) { + distance = d; + longest = i; + } + } + + double x0 = segments.getQuick(longest - 2); + double y0 = segments.getQuick(longest - 1); + double x1 = segments.getQuick(longest); + double y1 = segments.getQuick(longest + 1); + + distance = Math.sqrt(distance); + centerPoint.setLocation((x0 + x1) / 2, (y0 + y1) / 2); + direction.setLocation((x1 - x0) / distance, (y1 - y0) / distance); + return segCount / 2; + } + +} \ No newline at end of file