No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BasicDrawing.java 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. package org.insa.graphics.drawing.components;
  2. import java.awt.BasicStroke;
  3. import java.awt.Color;
  4. import java.awt.Graphics;
  5. import java.awt.Graphics2D;
  6. import java.awt.Image;
  7. import java.awt.event.ActionEvent;
  8. import java.awt.event.ActionListener;
  9. import java.awt.event.MouseAdapter;
  10. import java.awt.event.MouseEvent;
  11. import java.awt.geom.AffineTransform;
  12. import java.awt.geom.NoninvertibleTransformException;
  13. import java.awt.geom.Point2D;
  14. import java.awt.image.BufferedImage;
  15. import java.io.IOException;
  16. import java.util.ArrayList;
  17. import java.util.Iterator;
  18. import java.util.List;
  19. import javax.swing.JPanel;
  20. import org.insa.graph.Arc;
  21. import org.insa.graph.Graph;
  22. import org.insa.graph.GraphStatistics.BoundingBox;
  23. import org.insa.graph.Node;
  24. import org.insa.graph.Path;
  25. import org.insa.graph.Point;
  26. import org.insa.graphics.drawing.BasicGraphPalette;
  27. import org.insa.graphics.drawing.Drawing;
  28. import org.insa.graphics.drawing.DrawingClickListener;
  29. import org.insa.graphics.drawing.GraphPalette;
  30. import org.insa.graphics.drawing.MercatorProjection;
  31. import org.insa.graphics.drawing.PlateCarreProjection;
  32. import org.insa.graphics.drawing.Projection;
  33. import org.insa.graphics.drawing.overlays.MarkerOverlay;
  34. import org.insa.graphics.drawing.overlays.MarkerUtils;
  35. import org.insa.graphics.drawing.overlays.Overlay;
  36. import org.insa.graphics.drawing.overlays.PathOverlay;
  37. import org.insa.graphics.drawing.overlays.PointSetOverlay;
  38. /**
  39. * Cette implementation de la classe Dessin produit vraiment un affichage (au
  40. * contraire de la classe DessinInvisible).
  41. */
  42. public class BasicDrawing extends JPanel implements Drawing {
  43. /**
  44. *
  45. */
  46. private static final long serialVersionUID = 96779785877771827L;
  47. private abstract class BasicOverlay implements Overlay {
  48. // Visible?
  49. protected boolean visible;
  50. // Color
  51. protected Color color;
  52. public BasicOverlay(Color color) {
  53. this.visible = true;
  54. this.color = color;
  55. }
  56. /**
  57. * @return The Z level of this overlay (>= 1).
  58. */
  59. public abstract int getZLevel();
  60. @Override
  61. public void setColor(Color color) {
  62. this.color = color;
  63. }
  64. @Override
  65. public Color getColor() {
  66. return this.color;
  67. }
  68. @Override
  69. public void setVisible(boolean visible) {
  70. this.visible = visible;
  71. BasicDrawing.this.repaint();
  72. }
  73. @Override
  74. public boolean isVisible() {
  75. return this.visible;
  76. }
  77. @Override
  78. public void delete() {
  79. BasicDrawing.this.overlays.remove(this);
  80. }
  81. /**
  82. * Draw the given overlay.
  83. */
  84. public void draw(Graphics2D g) {
  85. if (this.visible) {
  86. drawImpl(g);
  87. }
  88. }
  89. public abstract void drawImpl(Graphics2D g);
  90. public void redraw() {
  91. BasicDrawing.this.repaint();
  92. }
  93. };
  94. private class BasicMarkerOverlay extends BasicOverlay implements MarkerOverlay {
  95. // Marker width and height
  96. public static final int MARKER_WIDTH = 30, MARKER_HEIGHT = 60;
  97. // Point of the marker.
  98. private Point point;
  99. // Image to draw
  100. private Image image;
  101. // Inner color and fill mode.
  102. private Color innerColor;
  103. private final AlphaMode alphaMode;
  104. public BasicMarkerOverlay(Point point, Color color, Color inner, AlphaMode alphaMode) {
  105. super(color);
  106. this.point = point;
  107. this.image = MarkerUtils.getMarkerForColor(color, inner, alphaMode);
  108. this.innerColor = inner;
  109. this.alphaMode = alphaMode;
  110. }
  111. public int getZLevel() {
  112. return 3;
  113. }
  114. @Override
  115. public Point getPoint() {
  116. return point;
  117. }
  118. @Override
  119. public void setColor(Color color) {
  120. this.innerColor = this.innerColor.equals(this.color) ? color : innerColor;
  121. super.setColor(color);
  122. this.image = MarkerUtils.getMarkerForColor(color, this.innerColor, alphaMode);
  123. }
  124. @Override
  125. public void moveTo(Point point) {
  126. this.point = point;
  127. BasicDrawing.this.repaint();
  128. }
  129. @Override
  130. public void drawImpl(Graphics2D graphics) {
  131. int px = projection.longitudeToPixelX(getPoint().getLongitude());
  132. int py = projection.latitudeToPixelY(getPoint().getLatitude());
  133. graphics.drawImage(this.image, px - MARKER_WIDTH / 2, py - MARKER_HEIGHT, MARKER_WIDTH,
  134. MARKER_HEIGHT, BasicDrawing.this);
  135. }
  136. };
  137. private class BasicPathOverlay extends BasicOverlay implements PathOverlay {
  138. // List of points
  139. private final List<Point> points;
  140. // Origin / Destination markers.
  141. private BasicMarkerOverlay origin, destination;
  142. public BasicPathOverlay(List<Point> points, Color color, BasicMarkerOverlay origin,
  143. BasicMarkerOverlay destination) {
  144. super(color);
  145. this.points = points;
  146. this.origin = origin;
  147. this.destination = destination;
  148. this.color = color;
  149. }
  150. public int getZLevel() {
  151. return 2;
  152. }
  153. @Override
  154. public void setColor(Color color) {
  155. super.setColor(color);
  156. this.origin.setColor(color);
  157. this.destination.setColor(color);
  158. }
  159. @Override
  160. public void drawImpl(Graphics2D graphics) {
  161. if (!points.isEmpty()) {
  162. graphics.setStroke(new BasicStroke(2));
  163. graphics.setColor(getColor());
  164. Iterator<Point> itPoint = points.iterator();
  165. Point prev = itPoint.next();
  166. while (itPoint.hasNext()) {
  167. Point curr = itPoint.next();
  168. int x1 = projection.longitudeToPixelX(prev.getLongitude());
  169. int x2 = projection.longitudeToPixelX(curr.getLongitude());
  170. int y1 = projection.latitudeToPixelY(prev.getLatitude());
  171. int y2 = projection.latitudeToPixelY(curr.getLatitude());
  172. graphics.drawLine(x1, y1, x2, y2);
  173. prev = curr;
  174. }
  175. }
  176. if (this.origin != null) {
  177. this.origin.draw(graphics);
  178. }
  179. if (this.destination != null) {
  180. this.destination.draw(graphics);
  181. }
  182. }
  183. };
  184. private class BasicPointSetOverlay extends BasicOverlay implements PointSetOverlay {
  185. // Default point width
  186. private static final int DEFAULT_POINT_WIDTH = 5;
  187. // Image for path / points
  188. private final BufferedImage image;
  189. private final Graphics2D graphics;
  190. private int width = DEFAULT_POINT_WIDTH;
  191. public BasicPointSetOverlay() {
  192. super(Color.BLACK);
  193. this.image = new BufferedImage(BasicDrawing.this.width, BasicDrawing.this.height,
  194. BufferedImage.TYPE_4BYTE_ABGR);
  195. this.graphics = image.createGraphics();
  196. this.graphics.setBackground(new Color(0, 0, 0, 0));
  197. }
  198. public int getZLevel() {
  199. return 1;
  200. }
  201. @Override
  202. public void setColor(Color color) {
  203. super.setColor(color);
  204. this.graphics.setColor(color);
  205. }
  206. @Override
  207. public void setWidth(int width) {
  208. this.width = Math.max(2, width);
  209. }
  210. @Override
  211. public void setWidthAndColor(int width, Color color) {
  212. setWidth(width);
  213. setColor(color);
  214. }
  215. @Override
  216. public void addPoint(Point point) {
  217. int x = projection.longitudeToPixelX(point.getLongitude()) - this.width / 2;
  218. int y = projection.latitudeToPixelY(point.getLatitude()) - this.width / 2;
  219. this.graphics.fillOval(x, y, this.width, this.width);
  220. BasicDrawing.this.repaint();
  221. }
  222. @Override
  223. public void addPoint(Point point, int width) {
  224. setWidth(width);
  225. addPoint(point);
  226. }
  227. @Override
  228. public void addPoint(Point point, Color color) {
  229. setColor(color);
  230. addPoint(point);
  231. }
  232. @Override
  233. public void addPoint(Point point, int width, Color color) {
  234. setWidth(width);
  235. setColor(color);
  236. addPoint(point);
  237. }
  238. @Override
  239. public void drawImpl(Graphics2D g) {
  240. g.drawImage(this.image, 0, 0, BasicDrawing.this);
  241. }
  242. }
  243. /**
  244. * Class encapsulating a set of overlays.
  245. *
  246. */
  247. private class BasicOverlays {
  248. // List of overlays.
  249. private ArrayList<ArrayList<BasicOverlay>> overlays = new ArrayList<>();
  250. public synchronized void draw(Graphics2D g) {
  251. // Clear overlays.
  252. for (ArrayList<BasicOverlay> arr: this.overlays) {
  253. for (BasicOverlay overlay: arr) {
  254. overlay.draw(g);
  255. }
  256. }
  257. }
  258. public synchronized void remove(BasicOverlay overlay) {
  259. overlays.get(overlay.getZLevel() - 1).remove(overlay);
  260. BasicDrawing.this.repaint();
  261. }
  262. public void clear() {
  263. clear(true);
  264. }
  265. public void clear(boolean repaint) {
  266. // Clear overlays.
  267. for (ArrayList<BasicOverlay> arr: this.overlays) {
  268. arr.clear();
  269. }
  270. // Repaint if requested.
  271. if (repaint) {
  272. BasicDrawing.this.repaint();
  273. }
  274. }
  275. public BasicOverlay add(BasicOverlay marker) {
  276. return add(marker, true);
  277. }
  278. public synchronized BasicOverlay add(BasicOverlay overlay, boolean repaint) {
  279. // Check if we have a level for this...
  280. for (int i = overlays.size(); i < overlay.getZLevel(); ++i) {
  281. overlays.add(new ArrayList<>());
  282. }
  283. // Add overlay to the given list.
  284. overlays.get(overlay.getZLevel() - 1).add(overlay);
  285. // Repaint if requested.
  286. if (repaint) {
  287. BasicDrawing.this.repaint();
  288. }
  289. return overlay;
  290. }
  291. };
  292. // Default path color.
  293. public static final Color DEFAULT_PATH_COLOR = new Color(66, 134, 244);
  294. // Default palette.
  295. public static final GraphPalette DEFAULT_PALETTE = new BasicGraphPalette();
  296. // Maximum width for the drawing (in pixels).
  297. private static final int MAXIMUM_DRAWING_WIDTH = 2000;
  298. private Projection projection;
  299. // Width and height of the image
  300. private int width, height;
  301. // Zoom controls
  302. private MapZoomControls zoomControls;
  303. private ZoomAndPanListener zoomAndPanListener;
  304. //
  305. private Image graphImage = null;
  306. private Graphics2D graphGraphics = null;
  307. // List of image for markers
  308. private BasicOverlays overlays = new BasicOverlays();
  309. // Mapping DrawingClickListener -> MouseEventListener
  310. private List<DrawingClickListener> drawingClickListeners = new ArrayList<>();
  311. /**
  312. * Create a new BasicDrawing.
  313. *
  314. */
  315. public BasicDrawing() {
  316. setLayout(null);
  317. this.setBackground(new Color(245, 245, 245));
  318. this.zoomAndPanListener = new ZoomAndPanListener(this,
  319. ZoomAndPanListener.DEFAULT_MIN_ZOOM_LEVEL, 20, 1.2);
  320. // Try...
  321. try {
  322. this.zoomControls = new MapZoomControls(this, 0,
  323. ZoomAndPanListener.DEFAULT_MIN_ZOOM_LEVEL, 20);
  324. this.zoomControls.addZoomInListener(new ActionListener() {
  325. @Override
  326. public void actionPerformed(ActionEvent e) {
  327. zoomAndPanListener.zoomIn();
  328. }
  329. });
  330. this.zoomControls.addZoomOutListener(new ActionListener() {
  331. @Override
  332. public void actionPerformed(ActionEvent e) {
  333. zoomAndPanListener.zoomOut();
  334. }
  335. });
  336. }
  337. catch (IOException e) {
  338. e.printStackTrace();
  339. }
  340. this.addMouseListener(new MouseAdapter() {
  341. @Override
  342. public void mouseClicked(MouseEvent evt) {
  343. if (zoomControls.contains(evt.getPoint())) {
  344. return;
  345. }
  346. Point lonlat = null;
  347. try {
  348. lonlat = getLongitudeLatitude(evt);
  349. }
  350. catch (NoninvertibleTransformException e) {
  351. return;
  352. }
  353. for (DrawingClickListener listener: drawingClickListeners) {
  354. listener.mouseClicked(lonlat);
  355. }
  356. }
  357. });
  358. }
  359. @Override
  360. public void paintComponent(Graphics g1) {
  361. super.paintComponent(g1);
  362. Graphics2D g = (Graphics2D) g1;
  363. AffineTransform sTransform = g.getTransform();
  364. g.setColor(this.getBackground());
  365. g.fillRect(0, 0, getWidth(), getHeight());
  366. g.setTransform(zoomAndPanListener.getCoordTransform());
  367. if (graphImage != null) {
  368. // Draw graph
  369. g.drawImage(graphImage, 0, 0, this);
  370. }
  371. // Draw markers
  372. this.overlays.draw(g);
  373. g.setTransform(sTransform);
  374. if (this.zoomControls != null) {
  375. this.zoomControls.setZoomLevel(this.zoomAndPanListener.getZoomLevel());
  376. this.zoomControls.draw(g, getWidth() - this.zoomControls.getWidth() - 20,
  377. this.getHeight() - this.zoomControls.getHeight() - 10, this);
  378. }
  379. }
  380. /*
  381. * (non-Javadoc)
  382. *
  383. * @see org.insa.graphics.drawing.Drawing#clear()
  384. */
  385. @Override
  386. public void clear() {
  387. if (this.graphGraphics != null) {
  388. this.graphGraphics.clearRect(0, 0, this.width, this.height);
  389. }
  390. this.overlays.clear(false);
  391. this.repaint();
  392. }
  393. /*
  394. * (non-Javadoc)
  395. *
  396. * @see org.insa.graphics.drawing.Drawing#clearOverlays()
  397. */
  398. @Override
  399. public void clearOverlays() {
  400. this.overlays.clear();
  401. }
  402. /**
  403. * @return The current ZoomAndPanListener associated with this drawing.
  404. */
  405. public ZoomAndPanListener getZoomAndPanListener() {
  406. return this.zoomAndPanListener;
  407. }
  408. /**
  409. * Return the longitude and latitude corresponding to the given position of the
  410. * MouseEvent.
  411. *
  412. * @param event MouseEvent from which longitude/latitude should be retrieved.
  413. *
  414. * @return Point representing the projection of the MouseEvent position in the
  415. * graph/map.
  416. *
  417. * @throws NoninvertibleTransformException if the actual transformation is
  418. * invalid.
  419. */
  420. protected Point getLongitudeLatitude(MouseEvent event) throws NoninvertibleTransformException {
  421. // Get the point using the inverse transform of the Zoom/Pan object, this gives
  422. // us
  423. // a point within the drawing box (between [0, 0] and [width, height]).
  424. Point2D ptDst = this.zoomAndPanListener.getCoordTransform()
  425. .inverseTransform(event.getPoint(), null);
  426. // Inverse the "projection" on x/y to get longitude and latitude.
  427. return new Point(projection.pixelXToLongitude(ptDst.getX()),
  428. projection.pixelYToLatitude(ptDst.getY()));
  429. }
  430. /*
  431. * (non-Javadoc)
  432. *
  433. * @see
  434. * org.insa.graphics.drawing.Drawing#addDrawingClickListener(org.insa.graphics.
  435. * drawing.DrawingClickListener)
  436. */
  437. @Override
  438. public void addDrawingClickListener(DrawingClickListener listener) {
  439. this.drawingClickListeners.add(listener);
  440. }
  441. /*
  442. * (non-Javadoc)
  443. *
  444. * @see org.insa.graphics.drawing.Drawing#removeDrawingClickListener(org.insa.
  445. * graphics.drawing.DrawingClickListener)
  446. */
  447. @Override
  448. public void removeDrawingClickListener(DrawingClickListener listener) {
  449. this.drawingClickListeners.remove(listener);
  450. }
  451. public BasicMarkerOverlay createMarker(Point point, Color outer, Color inner, AlphaMode mode) {
  452. return new BasicMarkerOverlay(point, outer, inner, mode);
  453. }
  454. @Override
  455. public MarkerOverlay drawMarker(Point point, Color outer, Color inner, AlphaMode mode) {
  456. return (MarkerOverlay) this.overlays.add(createMarker(point, outer, inner, mode));
  457. }
  458. @Override
  459. public PointSetOverlay createPointSetOverlay() {
  460. return (PointSetOverlay) this.overlays.add(new BasicPointSetOverlay(), false);
  461. }
  462. @Override
  463. public PointSetOverlay createPointSetOverlay(int width, Color color) {
  464. PointSetOverlay ps = createPointSetOverlay();
  465. ps.setWidthAndColor(width, color);
  466. return ps;
  467. }
  468. /**
  469. * Draw the given arc.
  470. *
  471. * @param arc Arc to draw.
  472. * @param palette Palette to use to retrieve color and width for arc, or null to
  473. * use current settings.
  474. */
  475. protected void drawArc(Arc arc, GraphPalette palette, boolean repaint) {
  476. List<Point> pts = arc.getPoints();
  477. if (!pts.isEmpty()) {
  478. if (palette != null) {
  479. this.graphGraphics.setColor(palette.getColorForArc(arc));
  480. this.graphGraphics.setStroke(new BasicStroke(palette.getWidthForArc(arc)));
  481. }
  482. Iterator<Point> it1 = pts.iterator();
  483. Point prev = it1.next();
  484. while (it1.hasNext()) {
  485. Point curr = it1.next();
  486. int x1 = projection.longitudeToPixelX(prev.getLongitude());
  487. int x2 = projection.longitudeToPixelX(curr.getLongitude());
  488. int y1 = projection.latitudeToPixelY(prev.getLatitude());
  489. int y2 = projection.latitudeToPixelY(curr.getLatitude());
  490. graphGraphics.drawLine(x1, y1, x2, y2);
  491. prev = curr;
  492. }
  493. }
  494. if (repaint) {
  495. this.repaint();
  496. }
  497. }
  498. /**
  499. * Initialize the drawing for the given graph.
  500. *
  501. * @param graph
  502. */
  503. protected void initialize(Graph graph) {
  504. // Clear everything.
  505. this.clear();
  506. BoundingBox box = graph.getGraphInformation().getBoundingBox();
  507. // Find minimum/maximum longitude and latitude.
  508. float minLon = box.getTopLeftPoint().getLongitude(),
  509. maxLon = box.getBottomRightPoint().getLongitude(),
  510. minLat = box.getBottomRightPoint().getLatitude(),
  511. maxLat = box.getTopLeftPoint().getLatitude();
  512. // Add a little delta to avoid drawing on the edge...
  513. float diffLon = maxLon - minLon, diffLat = maxLat - minLat;
  514. float deltaLon = 0.01f * diffLon, deltaLat = 0.01f * diffLat;
  515. // Create the projection and retrieve width and height for the box.
  516. BoundingBox extendedBox = box.extend(deltaLon, deltaLat, deltaLon, deltaLat);
  517. // Special projection for non-realistic maps...
  518. if (graph.getMapId().startsWith("0x")) {
  519. projection = new PlateCarreProjection(extendedBox, MAXIMUM_DRAWING_WIDTH / 4);
  520. }
  521. else {
  522. projection = new MercatorProjection(extendedBox, MAXIMUM_DRAWING_WIDTH);
  523. }
  524. this.width = (int) projection.getImageWidth();
  525. this.height = (int) projection.getImageHeight();
  526. // Create the image
  527. BufferedImage img = new BufferedImage(this.width, this.height,
  528. BufferedImage.TYPE_3BYTE_BGR);
  529. this.graphImage = img;
  530. this.graphGraphics = img.createGraphics();
  531. this.graphGraphics.setBackground(this.getBackground());
  532. this.graphGraphics.clearRect(0, 0, this.width, this.height);
  533. // Set the zoom and pan listener
  534. double scale = 1 / Math.max(this.width / (double) this.getWidth(),
  535. this.height / (double) this.getHeight());
  536. this.zoomAndPanListener.setCoordTransform(this.graphGraphics.getTransform());
  537. this.zoomAndPanListener.getCoordTransform().translate(
  538. (this.getWidth() - this.width * scale) / 2,
  539. (this.getHeight() - this.height * scale) / 2);
  540. this.zoomAndPanListener.getCoordTransform().scale(scale, scale);
  541. this.zoomAndPanListener.setZoomLevel(0);
  542. this.zoomControls.setZoomLevel(0);
  543. // Repaint
  544. this.repaint();
  545. }
  546. @Override
  547. public void drawGraph(Graph graph, GraphPalette palette) {
  548. int repaintModulo = Math.max(1, graph.size() / 100);
  549. // Initialize the buffered image
  550. this.initialize(graph);
  551. // Remove zoom and pan listener
  552. this.removeMouseListener(zoomAndPanListener);
  553. this.removeMouseMotionListener(zoomAndPanListener);
  554. this.removeMouseWheelListener(zoomAndPanListener);
  555. for (Node node: graph) {
  556. for (Arc arc: node) {
  557. // Draw arcs only if there are one-way arcs or if origin is lower than
  558. // destination, avoid drawing two-ways arc twice.
  559. if (arc.getRoadInformation().isOneWay()
  560. || arc.getOrigin().compareTo(arc.getDestination()) < 0) {
  561. drawArc(arc, palette, false);
  562. }
  563. }
  564. if (node.getId() % repaintModulo == 0) {
  565. this.repaint();
  566. }
  567. }
  568. this.repaint();
  569. // Re-add zoom and pan listener
  570. this.addMouseListener(zoomAndPanListener);
  571. this.addMouseMotionListener(zoomAndPanListener);
  572. this.addMouseWheelListener(zoomAndPanListener);
  573. }
  574. @Override
  575. public void drawGraph(Graph graph) {
  576. drawGraph(graph, DEFAULT_PALETTE);
  577. }
  578. @Override
  579. public PathOverlay drawPath(Path path, Color color, boolean markers) {
  580. List<Point> points = new ArrayList<Point>();
  581. if (!path.isEmpty()) {
  582. points.add(path.getOrigin().getPoint());
  583. for (Arc arc: path.getArcs()) {
  584. Iterator<Point> itPoint = arc.getPoints().iterator();
  585. // Discard origin each time
  586. itPoint.next();
  587. while (itPoint.hasNext()) {
  588. points.add(itPoint.next());
  589. }
  590. }
  591. }
  592. BasicMarkerOverlay origin = null, destination = null;
  593. if (markers && !path.isEmpty()) {
  594. origin = createMarker(path.getOrigin().getPoint(), color, color, AlphaMode.TRANSPARENT);
  595. destination = createMarker(path.getDestination().getPoint(), color, color,
  596. AlphaMode.TRANSPARENT);
  597. }
  598. return (PathOverlay) this.overlays
  599. .add(new BasicPathOverlay(points, color, origin, destination));
  600. }
  601. @Override
  602. public PathOverlay drawPath(Path path, Color color) {
  603. return drawPath(path, color, true);
  604. }
  605. @Override
  606. public PathOverlay drawPath(Path path) {
  607. return drawPath(path, DEFAULT_PATH_COLOR);
  608. }
  609. @Override
  610. public PathOverlay drawPath(Path path, boolean markers) {
  611. return drawPath(path, DEFAULT_PATH_COLOR, markers);
  612. }
  613. }