1 /*
2  * Copyright (c) 2016 Vivid Solutions.
3  *
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
7  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
8  * and the Eclipse Distribution License is available at
9  *
10  * http://www.eclipse.org/org/documents/edl-v10.php.
11  */
12 
13 package org.locationtech.jts.triangulate;
14 
15 import org.locationtech.jts.geom.Coordinate;
16 import org.locationtech.jts.geom.LineSegment;
17 
18 /**
19  * Models a constraint segment which can be split in two in various ways,
20  * according to certain geometric constraints.
21  *
22  * @author Martin Davis
23  */
24 public class SplitSegment {
25     /**
26      * Computes the {@link Coordinate} that lies a given fraction along the line defined by the
27      * reverse of the given segment. A fraction of <code>0.0</code> returns the end point of the
28      * segment; a fraction of <code>1.0</code> returns the start point of the segment.
29      *
30      * @param seg the LineSegment
31      * @param segmentLengthFraction the fraction of the segment length along the line
32      * @return the point at that distance
33      */
pointAlongReverse(LineSegment seg, double segmentLengthFraction)34     private static Coordinate pointAlongReverse(LineSegment seg, double segmentLengthFraction) {
35         Coordinate coord = new Coordinate();
36         coord.x = seg.p1.x - segmentLengthFraction * (seg.p1.x - seg.p0.x);
37         coord.y = seg.p1.y - segmentLengthFraction * (seg.p1.y - seg.p0.y);
38         return coord;
39     }
40 
41     private LineSegment seg;
42     private double      segLen;
43     private Coordinate  splitPt;
44     private double      minimumLen = 0.0;
45 
SplitSegment(LineSegment seg)46     public SplitSegment(LineSegment seg) {
47         this.seg = seg;
48         segLen = seg.getLength();
49     }
50 
setMinimumLength(double minLen)51     public void setMinimumLength(double minLen) {
52         minimumLen = minLen;
53     }
54 
getSplitPoint()55     public Coordinate getSplitPoint() {
56         return splitPt;
57     }
58 
splitAt(double length, Coordinate endPt)59     public void splitAt(double length, Coordinate endPt) {
60         double actualLen = getConstrainedLength(length);
61         double frac = actualLen / segLen;
62         if (endPt.equals2D(seg.p0))
63             splitPt = seg.pointAlong(frac);
64         else
65             splitPt = pointAlongReverse(seg, frac);
66     }
67 
splitAt(Coordinate pt)68     public void splitAt(Coordinate pt) {
69         // check that given pt doesn't violate min length
70         double minFrac = minimumLen / segLen;
71         if (pt.distance(seg.p0) < minimumLen) {
72             splitPt = seg.pointAlong(minFrac);
73             return;
74         }
75         if (pt.distance(seg.p1) < minimumLen) {
76             splitPt = pointAlongReverse(seg, minFrac);
77             return;
78         }
79         // passes minimum distance check - use provided point as split pt
80         splitPt = pt;
81     }
82 
getConstrainedLength(double len)83     private double getConstrainedLength(double len) {
84         if (len < minimumLen)
85             return minimumLen;
86         return len;
87     }
88 
89 }
90