1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.samples.geometry;
23
24 import java.awt.BorderLayout;
25 import java.awt.Color;
26 import java.awt.Component;
27 import java.awt.event.ActionEvent;
28 import java.awt.event.ActionListener;
29 import java.awt.geom.Point2D;
30 import java.util.ArrayList;
31 import java.util.List;
32
33 import javax.swing.BorderFactory;
34 import javax.swing.JButton;
35 import javax.swing.JComponent;
36 import javax.swing.JPanel;
37 import javax.swing.JSplitPane;
38
39 import org.hipparchus.geometry.enclosing.Encloser;
40 import org.hipparchus.geometry.enclosing.EnclosingBall;
41 import org.hipparchus.geometry.enclosing.WelzlEncloser;
42 import org.hipparchus.geometry.euclidean.twod.DiskGenerator;
43 import org.hipparchus.geometry.euclidean.twod.Euclidean2D;
44 import org.hipparchus.geometry.euclidean.twod.Segment;
45 import org.hipparchus.geometry.euclidean.twod.Vector2D;
46 import org.hipparchus.geometry.euclidean.twod.hull.ConvexHull2D;
47 import org.hipparchus.geometry.euclidean.twod.hull.ConvexHullGenerator2D;
48 import org.hipparchus.geometry.euclidean.twod.hull.MonotoneChain;
49 import org.hipparchus.random.MersenneTwister;
50 import org.hipparchus.random.RandomGenerator;
51 import org.hipparchus.samples.ExampleUtils;
52 import org.hipparchus.samples.ExampleUtils.ExampleFrame;
53 import org.hipparchus.util.FastMath;
54 import org.hipparchus.util.SinCos;
55 import org.piccolo2d.PCamera;
56 import org.piccolo2d.PCanvas;
57 import org.piccolo2d.PNode;
58 import org.piccolo2d.event.PBasicInputEventHandler;
59 import org.piccolo2d.event.PInputEvent;
60 import org.piccolo2d.event.PMouseWheelZoomEventHandler;
61 import org.piccolo2d.nodes.PPath;
62 import org.piccolo2d.nodes.PText;
63
64
65
66
67
68
69
70
71
72 public class GeometryExample {
73
74
75 private static final String TOOLTIP = "tooltip";
76
77
78
79
80
81
82
83
84 public GeometryExample() {
85
86 }
87
88
89
90
91
92 public static List<Vector2D> createRandomPoints(int size) {
93 RandomGenerator random = new MersenneTwister();
94
95
96 List<Vector2D> points = new ArrayList<Vector2D>(size);
97
98 for (int i = 0; i < size; i++) {
99 points.add(new Vector2D(FastMath.round(random.nextDouble() * 400 + 100),
100 FastMath.round(random.nextDouble() * 400 + 100)));
101 }
102
103 return points;
104 }
105
106
107
108
109
110 public static List<Vector2D> createCircle(int samples) {
111 List<Vector2D> points = new ArrayList<Vector2D>();
112 final Vector2D center = new Vector2D(300, 300);
113 double range = 2.0 * FastMath.PI;
114 double step = range / (samples + 1);
115 for (double angle = 0; angle < range; angle += step) {
116 Vector2D circle = buildVector(angle);
117 points.add(circle.scalarMultiply(200).add(center));
118 }
119
120 return points;
121 }
122
123
124
125
126 public static List<Vector2D> createCross() {
127 List<Vector2D> points = new ArrayList<Vector2D>();
128
129 for (int i = 100; i < 500; i += 10) {
130 points.add(new Vector2D(300, i));
131 points.add(new Vector2D(i, 300));
132 }
133
134 return points;
135 }
136
137
138
139
140 public static PCanvas createCanvas() {
141 final PCanvas canvas = new PCanvas();
142 final PCamera camera = canvas.getCamera();
143
144 final PText tooltipNode = new PText();
145 tooltipNode.setPickable(false);
146 camera.addChild(tooltipNode);
147
148 camera.addInputEventListener(new PBasicInputEventHandler() {
149 public void mouseMoved(final PInputEvent event) {
150 updateToolTip(event);
151 }
152
153 public void mouseDragged(final PInputEvent event) {
154 updateToolTip(event);
155 }
156
157 public void updateToolTip(final PInputEvent event) {
158 final PNode n = event.getPickedNode();
159 final Object object = (Object) n.getAttribute(TOOLTIP);
160 if (object != null) {
161 final String tooltipString = object.toString();
162 final Point2D p = event.getCanvasPosition();
163
164 event.getPath().canvasToLocal(p, camera);
165
166 tooltipNode.setText(tooltipString);
167 tooltipNode.setOffset(p.getX() + 8, p.getY() - 8);
168 } else {
169 tooltipNode.setText(null);
170 }
171 }
172 });
173
174
175 canvas.removeInputEventListener(canvas.getZoomEventHandler());
176
177
178 final PMouseWheelZoomEventHandler mouseWheelZoomEventHandler = new PMouseWheelZoomEventHandler();
179 canvas.addInputEventListener(mouseWheelZoomEventHandler);
180
181 return canvas;
182 }
183
184
185
186
187
188
189 private static Vector2D buildVector(final double alpha) {
190 final SinCos sc = FastMath.sinCos(alpha);
191 return new Vector2D(sc.cos(), sc.sin());
192 }
193
194
195
196 @SuppressWarnings("serial")
197 public static class Display extends ExampleFrame {
198
199
200 private List<Vector2D> points;
201
202
203 private PCanvas canvas;
204
205
206 private JComponent container;
207
208
209
210 public Display() {
211 setTitle("Hipparchus: Geometry Examples");
212 setSize(800, 700);
213
214 container = new JPanel(new BorderLayout());
215 canvas = createCanvas();
216 container.add(canvas);
217 container.setBorder(BorderFactory.createLineBorder(Color.black, 1));
218
219 JComponent controlPanel = new JPanel();
220 JButton random = new JButton("Randomize");
221 controlPanel.add(random);
222
223 random.addActionListener(new ActionListener() {
224
225
226 public void actionPerformed(ActionEvent e) {
227 canvas.getLayer().removeAllChildren();
228
229 points = createRandomPoints(1000);
230 paintConvexHull();
231 }
232 });
233
234 JButton circle = new JButton("Circle");
235 controlPanel.add(circle);
236
237 circle.addActionListener(new ActionListener() {
238
239
240 public void actionPerformed(ActionEvent e) {
241 canvas.getLayer().removeAllChildren();
242
243 points = createCircle(100);
244 paintConvexHull();
245 }
246 });
247
248 JButton cross = new JButton("Cross");
249 controlPanel.add(cross);
250
251 cross.addActionListener(new ActionListener() {
252
253
254 public void actionPerformed(ActionEvent e) {
255 canvas.getLayer().removeAllChildren();
256
257 points = createCross();
258 paintConvexHull();
259 }
260 });
261
262 JSplitPane splitpane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, container,
263 controlPanel);
264 splitpane.setDividerLocation(600);
265
266 add(splitpane);
267
268 points = createRandomPoints(1000);
269 paintConvexHull();
270 }
271
272
273 @Override
274 public Component getMainPanel() {
275 return container;
276 }
277
278
279
280 public void paintConvexHull() {
281 PNode pointSet = new PNode();
282 for (Vector2D point : points) {
283 final PNode node = PPath.createEllipse(point.getX() - 1, point.getY() - 1, 2, 2);
284 node.addAttribute(TOOLTIP, point);
285 node.setPaint(Color.gray);
286 pointSet.addChild(node);
287 }
288
289 canvas.getLayer().addChild(pointSet);
290
291 ConvexHullGenerator2D generator = new MonotoneChain(true, 1e-6);
292 ConvexHull2D hull = generator.generate(points);
293
294 PNode hullNode = new PNode();
295 for (Vector2D vertex : hull.getVertices()) {
296 final PPath node = PPath.createEllipse(vertex.getX() - 1, vertex.getY() - 1, 2, 2);
297 node.addAttribute(TOOLTIP, vertex);
298 node.setPaint(Color.red);
299 node.setStrokePaint(Color.red);
300 hullNode.addChild(node);
301 }
302
303 for (Segment line : hull.getLineSegments()) {
304 final PPath node = PPath.createLine(line.getStart().getX(), line.getStart().getY(),
305 line.getEnd().getX(), line.getEnd().getY());
306 node.setPickable(false);
307 node.setPaint(Color.red);
308 node.setStrokePaint(Color.red);
309 hullNode.addChild(node);
310 }
311
312 canvas.getLayer().addChild(hullNode);
313
314 Encloser<Euclidean2D, Vector2D> encloser =
315 new WelzlEncloser<Euclidean2D, Vector2D>(1e-10, new DiskGenerator());
316 EnclosingBall<Euclidean2D, Vector2D> ball = encloser.enclose(points);
317
318 final double radius = ball.getRadius();
319 PPath ballCenter =
320 PPath.createEllipse(ball.getCenter().getX() - 1, ball.getCenter().getY() - 1, 2, 2);
321 ballCenter.setStrokePaint(Color.blue);
322 ballCenter.setPaint(Color.blue);
323 canvas.getLayer().addChild(0, ballCenter);
324
325 PPath ballNode =
326 PPath.createEllipse(ball.getCenter().getX() - radius, ball.getCenter().getY() - radius,
327 radius * 2, radius * 2);
328 ballNode.setTransparency(1.0f);
329 ballNode.setStrokePaint(Color.blue);
330 canvas.getLayer().addChild(0, ballNode);
331 }
332 }
333
334
335
336
337 public static void main(final String[] argv) {
338 ExampleUtils.showExampleFrame(new Display());
339 }
340
341 }