/** * {@inheritDoc} * * @param positions Control points. This graphic uses only two control point, which determine the * midpoints of two opposite sides of the quad. See Fire Support Area (2.X.4.3.2.1.2) on pg. * 652 of MIL-STD-2525C for an example of how these points are interpreted. */ public void setPositions(Iterable<? extends Position> positions) { if (positions == null) { String message = Logging.getMessage("nullValue.PositionsListIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } Iterator<? extends Position> iterator = positions.iterator(); try { Position pos1 = iterator.next(); Position pos2 = iterator.next(); LatLon center = LatLon.interpolateGreatCircle(0.5, pos1, pos2); this.quad.setCenter(center); Angle heading = LatLon.greatCircleAzimuth(pos2, pos1); this.quad.setHeading(heading.subtract(Angle.POS90)); this.positions = positions; this.shapeInvalid = true; // Need to recompute quad size } catch (NoSuchElementException e) { String message = Logging.getMessage("generic.InsufficientPositions"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } }
protected List<Position> computePathPositions( Position startPosition, Position endPosition, Angle delta) { Angle dist = LatLon.greatCircleDistance(startPosition, endPosition); dist = dist.multiply(0.6); Angle azimuth = LatLon.greatCircleAzimuth(startPosition, endPosition); LatLon locA = LatLon.greatCircleEndPosition(startPosition, azimuth.add(delta), dist); dist = dist.multiply(0.9); LatLon locB = LatLon.greatCircleEndPosition(startPosition, azimuth.subtract(delta), dist); return Arrays.asList(startPosition, new Position(locA, 0), new Position(locB, 0), endPosition); }
protected double[] computeAngles() { // Compute the start and sweep angles such that the partial cylinder shape tranverses a // clockwise path from // the start angle to the stop angle. Angle startAngle, stopAngle, sweepAngle; startAngle = normalizedAzimuth(this.leftAzimuth); stopAngle = normalizedAzimuth(this.rightAzimuth); int i = startAngle.compareTo(stopAngle); // Angles are equal, fallback to building a closed cylinder. if (i == 0) return null; if (i < 0) sweepAngle = stopAngle.subtract(startAngle); else // (i > 0) sweepAngle = Angle.POS360.subtract(startAngle).add(stopAngle); double[] array = new double[3]; array[0] = startAngle.radians; array[1] = stopAngle.radians; array[2] = sweepAngle.radians; return array; }
/** * Create the list of positions that describe the arrow. * * @param dc Current draw context. */ protected void createShapes(DrawContext dc) { this.paths = new Path[2]; int i = 0; Angle azimuth1 = LatLon.greatCircleAzimuth(this.position1, this.position2); Angle azimuth2 = LatLon.greatCircleAzimuth(this.position1, this.position3); Angle delta = azimuth2.subtract(azimuth1); int sign = delta.degrees > 0 ? 1 : -1; delta = Angle.fromDegrees(sign * 5.0); // Create a path for the line part of the arrow List<Position> positions = this.computePathPositions(this.position1, this.position2, delta); this.paths[i++] = this.createPath(positions); // Create a polygon to draw the arrow head. double arrowLength = this.getArrowLength(); Angle arrowAngle = this.getArrowAngle(); positions = this.computeArrowheadPositions( dc, positions.get(2), positions.get(3), arrowLength, arrowAngle); this.arrowHead1 = this.createPolygon(positions); this.arrowHead1.setLocations(positions); delta = delta.multiply(-1.0); positions = this.computePathPositions(this.position1, this.position3, delta); this.paths[i] = this.createPath(positions); positions = this.computeArrowheadPositions( dc, positions.get(2), positions.get(3), arrowLength, arrowAngle); this.arrowHead2 = this.createPolygon(positions); this.arrowHead2.setLocations(positions); }