/** * Computes the fraction of distance (in <tt>[0.0, 1.0]</tt>) * that the projection of a point occurs along this line segment. * If the point is beyond either ends of the line segment, * the closest fractional value (<tt>0.0</tt> or <tt>1.0</tt>) is returned. * <p> * Essentially, this is the {@link #projectionFactor} clamped to * the range <tt>[0.0, 1.0]</tt>. * If the segment has zero length, 1.0 is returned. * * @param inputPt the point * @return the fraction along the line segment the projection of the point occurs */ public double segmentFraction( Coordinate inputPt) { double segFrac = projectionFactor(inputPt); if (segFrac < 0.0) segFrac = 0.0; else if (segFrac > 1.0 || Double.isNaN(segFrac)) segFrac = 1.0; return segFrac; }
/** * Compute the projection of a point onto the line determined * by this line segment. * <p> * Note that the projected point * may lie outside the line segment. If this is the case, * the projection factor will lie outside the range [0.0, 1.0]. */ public Coordinate project(Coordinate p) { if (p.equals(p0) || p.equals(p1)) return new Coordinate(p); double r = projectionFactor(p); Coordinate coord = new Coordinate(); coord.x = p0.x + r * (p1.x - p0.x); coord.y = p0.y + r * (p1.y - p0.y); return coord; } /**
private double segmentNearestMeasure(LineSegment seg, Coordinate inputPt, double segmentStartMeasure) { // found new minimum, so compute location distance of point double projFactor = seg.projectionFactor(inputPt); if (projFactor <= 0.0) return segmentStartMeasure; if (projFactor <= 1.0) return segmentStartMeasure + projFactor * seg.getLength(); // projFactor > 1.0 return segmentStartMeasure + seg.getLength(); } }
/** * Project a line segment onto this line segment and return the resulting * line segment. The returned line segment will be a subset of * the target line line segment. This subset may be null, if * the segments are oriented in such a way that there is no projection. * <p> * Note that the returned line may have zero length (i.e. the same endpoints). * This can happen for instance if the lines are perpendicular to one another. * * @param seg the line segment to project * @return the projected line segment, or <code>null</code> if there is no overlap */ public LineSegment project(LineSegment seg) { double pf0 = projectionFactor(seg.p0); double pf1 = projectionFactor(seg.p1); // check if segment projects at all if (pf0 >= 1.0 && pf1 >= 1.0) return null; if (pf0 <= 0.0 && pf1 <= 0.0) return null; Coordinate newp0 = project(seg.p0); if (pf0 < 0.0) newp0 = p0; if (pf0 > 1.0) newp0 = p1; Coordinate newp1 = project(seg.p1); if (pf1 < 0.0) newp1 = p0; if (pf1 > 1.0) newp1 = p1; return new LineSegment(newp0, newp1); } /**
/** * Computes the closest point on this line segment to another point. * @param p the point to find the closest point to * @return a Coordinate which is the closest point on the line segment to the point p */ public Coordinate closestPoint(Coordinate p) { double factor = projectionFactor(p); if (factor > 0 && factor < 1) { return project(p); } double dist0 = p0.distance(p); double dist1 = p1.distance(p); if (dist0 < dist1) return p0; return p1; } /**
/** * Computes the fraction of distance (in <tt>[0.0, 1.0]</tt>) * that the projection of a point occurs along this line segment. * If the point is beyond either ends of the line segment, * the closest fractional value (<tt>0.0</tt> or <tt>1.0</tt>) is returned. * <p> * Essentially, this is the {@link #projectionFactor} clamped to * the range <tt>[0.0, 1.0]</tt>. * If the segment has zero length, 1.0 is returned. * * @param inputPt the point * @return the fraction along the line segment the projection of the point occurs */ public double segmentFraction( Coordinate inputPt) { double segFrac = projectionFactor(inputPt); if (segFrac < 0.0) segFrac = 0.0; else if (segFrac > 1.0 || Double.isNaN(segFrac)) segFrac = 1.0; return segFrac; }
/** * Compute the projection of a point onto the line determined * by this line segment. * <p> * Note that the projected point * may lie outside the line segment. If this is the case, * the projection factor will lie outside the range [0.0, 1.0]. */ public Coordinate project(Coordinate p) { if (p.equals(p0) || p.equals(p1)) return new Coordinate(p); double r = projectionFactor(p); Coordinate coord = new Coordinate(); coord.x = p0.x + r * (p1.x - p0.x); coord.y = p0.y + r * (p1.y - p0.y); return coord; } /**
private double segmentNearestMeasure(LineSegment seg, Coordinate inputPt, double segmentStartMeasure) { // found new minimum, so compute location distance of point double projFactor = seg.projectionFactor(inputPt); if (projFactor <= 0.0) return segmentStartMeasure; if (projFactor <= 1.0) return segmentStartMeasure + projFactor * seg.getLength(); // projFactor > 1.0 return segmentStartMeasure + seg.getLength(); } }
/** * Project a line segment onto this line segment and return the resulting * line segment. The returned line segment will be a subset of * the target line line segment. This subset may be null, if * the segments are oriented in such a way that there is no projection. * <p> * Note that the returned line may have zero length (i.e. the same endpoints). * This can happen for instance if the lines are perpendicular to one another. * * @param seg the line segment to project * @return the projected line segment, or <code>null</code> if there is no overlap */ public LineSegment project(LineSegment seg) { double pf0 = projectionFactor(seg.p0); double pf1 = projectionFactor(seg.p1); // check if segment projects at all if (pf0 >= 1.0 && pf1 >= 1.0) return null; if (pf0 <= 0.0 && pf1 <= 0.0) return null; Coordinate newp0 = project(seg.p0); if (pf0 < 0.0) newp0 = p0; if (pf0 > 1.0) newp0 = p1; Coordinate newp1 = project(seg.p1); if (pf1 < 0.0) newp1 = p0; if (pf1 > 1.0) newp1 = p1; return new LineSegment(newp0, newp1); } /**
/** * Computes the closest point on this line segment to another point. * @param p the point to find the closest point to * @return a Coordinate which is the closest point on the line segment to the point p */ public Coordinate closestPoint(Coordinate p) { double factor = projectionFactor(p); if (factor > 0 && factor < 1) { return project(p); } double dist0 = p0.distance(p); double dist1 = p1.distance(p); if (dist0 < dist1) return p0; return p1; } /**
private void updateLength(LineSegment seg, Coordinate inputPt, double segStartLocationDistance) { double dist = seg.distance(inputPt); if (dist > minDistanceToPoint) return; minDistanceToPoint = dist; // found new minimum, so compute location distance of point double projFactor = seg.projectionFactor(inputPt); if (projFactor <= 0.0) locationLength = segStartLocationDistance; else if (projFactor <= 1.0) locationLength = segStartLocationDistance + projFactor * seg.getLength(); else locationLength = segStartLocationDistance + seg.getLength(); } }
/** * Compute intersection point of two vectors * @param p1 Origin point * @param v1 Direction from p1 * @param p2 Origin point 2 * @param v2 Direction of p2 * @return Null if vectors are collinear or if intersection is done behind one of origin point */ public static Coordinate vectorIntersection(Coordinate p1, Vector3D v1, Coordinate p2, Vector3D v2) { double delta; Coordinate i = null; // Cramer's rule for compute intersection of two planes delta = v1.getX() * (-v2.getY()) - (-v1.getY()) * v2.getX(); if (delta != 0) { double k = ((p2.x - p1.x) * (-v2.getY()) - (p2.y - p1.y) * (-v2.getX())) / delta; // Fix precision problem with big decimal i = new Coordinate(p1.x + k * v1.getX(), p1.y + k * v1.getY(), p1.z + k * v1.getZ()); if(new LineSegment(p1, new Coordinate(p1.x + v1.getX(), p1.y + v1.getY())).projectionFactor(i) < 0 || new LineSegment(p2, new Coordinate(p2.x + v2.getX(), p2.y + v2.getY())).projectionFactor(i) < 0) { return null; } } return i; }
/** * Compute intersection point of two vectors * @param p1 Origin point * @param v1 Direction from p1 * @param p2 Origin point 2 * @param v2 Direction of p2 * @return Null if vectors are collinear or if intersection is done behind one of origin point */ public static Coordinate vectorIntersection(Coordinate p1, Vector3D v1, Coordinate p2, Vector3D v2) { double delta; Coordinate i = null; // Cramer's rule for compute intersection of two planes delta = v1.getX() * (-v2.getY()) - (-v1.getY()) * v2.getX(); if (delta != 0) { double k = ((p2.x - p1.x) * (-v2.getY()) - (p2.y - p1.y) * (-v2.getX())) / delta; // Fix precision problem with big decimal i = new Coordinate(p1.x + k * v1.getX(), p1.y + k * v1.getY(), p1.z + k * v1.getZ()); if(new LineSegment(p1, new Coordinate(p1.x + v1.getX(), p1.y + v1.getY())).projectionFactor(i) < 0 || new LineSegment(p2, new Coordinate(p2.x + v2.getX(), p2.y + v2.getY())).projectionFactor(i) < 0) { return null; } } return i; }
if (d <= tolerance && d <= minDist) { MCoordinate testcp = new MCoordinate(cp); projfact = seg.projectionFactor(cp); testcp.m = ((MCoordinate) coAr[i - 1]).m + projfact