public int XcompareTo(Object obj) { DepthSegment other = (DepthSegment) obj; // if segments are collinear and vertical compare endpoints if (isVertical() && other.isVertical() && upwardSeg.p0.x == other.upwardSeg.p0.x) return compareX(this.upwardSeg, other.upwardSeg); // check if segments are trivially ordered along X if (upwardSeg.maxX() <= other.upwardSeg.minX()) return -1; if (upwardSeg.minX() >= other.upwardSeg.maxX()) return 1; /** * try and compute a determinate orientation for the segments. Test returns 1 if other is left * of this (i.e. this > other) */ int orientIndex = upwardSeg.orientationIndex(other.upwardSeg); // if orientation is determinate, return it if (orientIndex != 0) return orientIndex; /** * If comparison between this and other is indeterminate, try the opposite call order. * orientationIndex value is 1 if this is left of other, so have to flip sign to get proper * comparison value of -1 if this is leftmost */ if (orientIndex == 0) orientIndex = -1 * other.upwardSeg.orientationIndex(upwardSeg); // if orientation is determinate, return it if (orientIndex != 0) return orientIndex; // otherwise, segs must be collinear - sort based on minimum X value return compareX(this.upwardSeg, other.upwardSeg); }
public static void computeDistance(LineString line, Coordinate pt, PointPairDistance ptDist) { LineSegment tempSegment = new LineSegment(); Coordinate[] coords = line.getCoordinates(); for (int i = 0; i < coords.length - 1; i++) { tempSegment.setCoordinates(coords[i], coords[i + 1]); // this is somewhat inefficient - could do better Coordinate closestPt = tempSegment.closestPoint(pt); ptDist.setMinimum(closestPt, pt); } }
private DepthSegment createRandomDepthSegment() { double scale = 10; int max = 10; double x0 = randint(max); double y0 = randint(max); double ang = 2 * Math.PI * Math.random(); double x1 = Math.rint(x0 + max * Math.cos(ang)); double y1 = Math.rint(y0 + max * Math.sin(ang)); LineSegment seg = new LineSegment(x0, y0, x1, y1); seg.normalize(); return new DepthSegment(seg, 0); }
/** * Defines a comparison operation on DepthSegments which orders them left to right * * <pre> * DS1 < DS2 if DS1.seg is left of DS2.seg * DS1 > DS2 if DS1.seg is right of DS2.seg * </pre> * * @param obj * @return the comparison value */ public int compareTo(Object obj) { DepthSegment other = (DepthSegment) obj; if (!envelopesOverlap(upwardSeg, other.upwardSeg)) return upwardSeg.compareTo(other.upwardSeg); // check orientations int orientIndex = upwardSeg.orientationIndex(other.upwardSeg); if (orientIndex != 0) return orientIndex; orientIndex = -other.upwardSeg.orientationIndex(upwardSeg); if (orientIndex != 0) return orientIndex; // segments cross or are collinear. Use segment ordering return upwardSeg.compareTo(other.upwardSeg); }
/** * Compute the width information for a ring of {@link Coordinate}s. Leaves the width information * in the instance variables. * * @param pts */ private void computeConvexRingMinDiameter(Coordinate[] pts) { // for each segment in the ring minWidth = Double.MAX_VALUE; int currMaxIndex = 1; LineSegment seg = new LineSegment(); // compute the max distance for all segments in the ring, and pick the minimum for (int i = 0; i < pts.length - 1; i++) { seg.p0 = pts[i]; seg.p1 = pts[i + 1]; currMaxIndex = findMaxPerpDistance(pts, seg, currMaxIndex); } }
public boolean envelopesOverlap(LineSegment seg1, LineSegment seg2) { if (seg1.maxX() <= seg2.minX()) return false; if (seg2.maxX() <= seg1.minX()) return false; if (seg1.maxY() <= seg2.minY()) return false; if (seg2.maxY() <= seg1.minY()) return false; return true; }
/** * Gets a {@link LineString} which is a minimum diameter * * @return a {@link LineString} which is a minimum diameter */ public LineString getDiameter() { computeMinimumDiameter(); // return empty linestring if no minimum width calculated if (minWidthPt == null) return inputGeom.getFactory().createLineString((Coordinate[]) null); Coordinate basePt = minBaseSeg.project(minWidthPt); return inputGeom.getFactory().createLineString(new Coordinate[] {basePt, minWidthPt}); }
private int findMaxPerpDistance(Coordinate[] pts, LineSegment seg, int startIndex) { double maxPerpDistance = seg.distancePerpendicular(pts[startIndex]); double nextPerpDistance = maxPerpDistance; int maxIndex = startIndex; int nextIndex = maxIndex; while (nextPerpDistance >= maxPerpDistance) { maxPerpDistance = nextPerpDistance; maxIndex = nextIndex; nextIndex = nextIndex(pts, maxIndex); nextPerpDistance = seg.distancePerpendicular(pts[nextIndex]); } // found maximum width for this segment - update global min dist if appropriate if (maxPerpDistance < minWidth) { minPtIndex = maxIndex; minWidth = maxPerpDistance; minWidthPt = pts[minPtIndex]; minBaseSeg = new LineSegment(seg); // System.out.println(minBaseSeg); // System.out.println(minWidth); } return maxIndex; }
private void computeWidthConvex(Geometry convexGeom) { // System.out.println("Input = " + geom); if (convexGeom instanceof Polygon) convexHullPts = ((Polygon) convexGeom).getExteriorRing().getCoordinates(); else convexHullPts = convexGeom.getCoordinates(); // special cases for lines or points or degenerate rings if (convexHullPts.length == 0) { minWidth = 0.0; minWidthPt = null; minBaseSeg = null; } else if (convexHullPts.length == 1) { minWidth = 0.0; minWidthPt = convexHullPts[0]; minBaseSeg.p0 = convexHullPts[0]; minBaseSeg.p1 = convexHullPts[0]; } else if (convexHullPts.length == 2 || convexHullPts.length == 3) { minWidth = 0.0; minWidthPt = convexHullPts[0]; minBaseSeg.p0 = convexHullPts[0]; minBaseSeg.p1 = convexHullPts[1]; } else computeConvexRingMinDiameter(convexHullPts); }
/** * Gets the minimum rectangular {@link Polygon} which encloses the input geometry. The rectangle * has width equal to the minimum diameter, and a longer length. If the convex hull of the input * is degenerate (a line or point) a {@link LineString} or {@link Point} is returned. * * <p>The minimum rectangle can be used as an extremely generalized representation for the given * geometry. * * @return the minimum rectangle enclosing the input (or a line or point if degenerate) */ public Geometry getMinimumRectangle() { computeMinimumDiameter(); // check if minimum rectangle is degenerate (a point or line segment) if (minWidth == 0.0) { if (minBaseSeg.p0.equals2D(minBaseSeg.p1)) { return inputGeom.getFactory().createPoint(minBaseSeg.p0); } return minBaseSeg.toGeometry(inputGeom.getFactory()); } // deltas for the base segment of the minimum diameter double dx = minBaseSeg.p1.x - minBaseSeg.p0.x; double dy = minBaseSeg.p1.y - minBaseSeg.p0.y; /* double c0 = computeC(dx, dy, minBaseSeg.p0); double c1 = computeC(dx, dy, minBaseSeg.p1); */ double minPara = Double.MAX_VALUE; double maxPara = -Double.MAX_VALUE; double minPerp = Double.MAX_VALUE; double maxPerp = -Double.MAX_VALUE; // compute maxima and minima of lines parallel and perpendicular to base segment for (int i = 0; i < convexHullPts.length; i++) { double paraC = computeC(dx, dy, convexHullPts[i]); if (paraC > maxPara) maxPara = paraC; if (paraC < minPara) minPara = paraC; double perpC = computeC(-dy, dx, convexHullPts[i]); if (perpC > maxPerp) maxPerp = perpC; if (perpC < minPerp) minPerp = perpC; } // compute lines along edges of minimum rectangle LineSegment maxPerpLine = computeSegmentForLine(-dx, -dy, maxPerp); LineSegment minPerpLine = computeSegmentForLine(-dx, -dy, minPerp); LineSegment maxParaLine = computeSegmentForLine(-dy, dx, maxPara); LineSegment minParaLine = computeSegmentForLine(-dy, dx, minPara); // compute vertices of rectangle (where the para/perp max & min lines intersect) Coordinate p0 = maxParaLine.lineIntersection(maxPerpLine); Coordinate p1 = minParaLine.lineIntersection(maxPerpLine); Coordinate p2 = minParaLine.lineIntersection(minPerpLine); Coordinate p3 = maxParaLine.lineIntersection(minPerpLine); LinearRing shell = inputGeom.getFactory().createLinearRing(new Coordinate[] {p0, p1, p2, p3, p0}); return inputGeom.getFactory().createPolygon(shell, null); }
public String toString() { return upwardSeg.toString(); }
public static void computeDistance(LineSegment segment, Coordinate pt, PointPairDistance ptDist) { Coordinate closestPt = segment.closestPoint(pt); ptDist.setMinimum(closestPt, pt); }