1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.geometry.spherical.twod;
18
19 import java.util.Collections;
20 import java.util.List;
21
22 import org.apache.commons.geometry.core.Transform;
23 import org.apache.commons.geometry.core.partitioning.Hyperplane;
24 import org.apache.commons.geometry.core.partitioning.HyperplaneConvexSubset;
25 import org.apache.commons.geometry.core.partitioning.Split;
26 import org.apache.commons.geometry.core.partitioning.SplitLocation;
27 import org.apache.commons.geometry.spherical.oned.AngularInterval;
28 import org.apache.commons.geometry.spherical.oned.CutAngle;
29 import org.apache.commons.geometry.spherical.oned.CutAngles;
30 import org.apache.commons.geometry.spherical.oned.Transform1S;
31
32
33
34
35
36
37
38
39
40
41
42 public final class GreatArc extends GreatCircleSubset implements HyperplaneConvexSubset<Point2S> {
43
44
45 private final AngularInterval.Convex interval;
46
47
48
49
50
51 GreatArc(final GreatCircle circle, final AngularInterval.Convex interval) {
52 super(circle);
53
54 this.interval = interval;
55 }
56
57
58
59
60 public Point2S getStartPoint() {
61 if (!interval.isFull()) {
62 return getCircle().toSpace(interval.getMinBoundary().getPoint());
63 }
64
65 return null;
66 }
67
68
69
70
71 public Point2S getEndPoint() {
72 if (!interval.isFull()) {
73 return getCircle().toSpace(interval.getMaxBoundary().getPoint());
74 }
75
76 return null;
77 }
78
79
80
81
82 public Point2S getMidPoint() {
83 if (!interval.isFull()) {
84 return getCircle().toSpace(interval.getMidPoint());
85 }
86
87 return null;
88 }
89
90
91
92
93
94 public AngularInterval.Convex getInterval() {
95 return interval;
96 }
97
98
99 @Override
100 public AngularInterval.Convex getSubspaceRegion() {
101 return getInterval();
102 }
103
104
105 @Override
106 public List<GreatArc> toConvex() {
107 return Collections.singletonList(this);
108 }
109
110
111 @Override
112 public Split<GreatArc> split(final Hyperplane<Point2S> splitter) {
113 final GreatCircle splitterCircle = (GreatCircle) splitter;
114 final GreatCircle thisCircle = getCircle();
115
116 final Point2S intersection = splitterCircle.intersection(thisCircle);
117
118 GreatArc minus = null;
119 GreatArc plus = null;
120
121 if (intersection != null) {
122
123
124 final CutAngle subSplitter = CutAngles.createNegativeFacing(
125 thisCircle.toSubspace(intersection), splitterCircle.getPrecision());
126
127 final Split<AngularInterval.Convex> subSplit = interval.splitDiameter(subSplitter);
128 final SplitLocation subLoc = subSplit.getLocation();
129
130 if (subLoc == SplitLocation.MINUS) {
131 minus = this;
132 } else if (subLoc == SplitLocation.PLUS) {
133 plus = this;
134 } else if (subLoc == SplitLocation.BOTH) {
135 minus = GreatCircles.arcFromInterval(thisCircle, subSplit.getMinus());
136 plus = GreatCircles.arcFromInterval(thisCircle, subSplit.getPlus());
137 }
138 }
139
140 return new Split<>(minus, plus);
141 }
142
143
144 @Override
145 public GreatArc transform(final Transform<Point2S> transform) {
146 return new GreatArc(getCircle().transform(transform), interval);
147 }
148
149
150 @Override
151 public GreatArc reverse() {
152 return new GreatArc(
153 getCircle().reverse(),
154 interval.transform(Transform1S.createNegation()));
155 }
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175 @Override
176 public String toString() {
177 final StringBuilder sb = new StringBuilder();
178 sb.append(this.getClass().getSimpleName()).append('[');
179
180 if (isFull()) {
181 sb.append("full= true, circle= ")
182 .append(getCircle());
183 } else {
184 sb.append("start= ")
185 .append(getStartPoint())
186 .append(", end= ")
187 .append(getEndPoint());
188 }
189
190 return sb.toString();
191 }
192 }