// ********************************************************************** // // // // BBN Technologies, a Verizon Company // 10 Moulton Street // Cambridge, MA 02138 // (617) 873-8000 // // Copyright (C) BBNT Solutions LLC. All rights reserved. // // // ********************************************************************** // // $Source: /cvs/openmap/openmap/src/openmap/com/bbn/openmap/omGraphics/OMDistance.java,v $ // $RCSfile: OMDistance.java,v $ // $Revision: 1.1.1.1 $ // $Date: 2003/03/03 21:58:09 $ // $Author: dietrick $ // // ********************************************************************** package com.bbn.openmap.omGraphics; import com.bbn.openmap.LatLonPoint; import com.bbn.openmap.MoreMath; import com.bbn.openmap.geo.Geo; import com.bbn.openmap.omGraphics.*; import com.bbn.openmap.proj.*; import com.bbn.openmap.util.Debug; /* CTM */ import java.io.IOException; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.awt.*; import java.awt.geom.*; import java.io.Serializable; import java.text.DecimalFormat; import java.util.ArrayList; /** * OMGraphic object that represents a polyline, labeled with distances. */ public class OMDistance extends OMPoly { protected OMGraphicList labels = new OMGraphicList(); protected OMGraphicList points = new OMGraphicList(); protected Length distUnits = Length.NM; public DecimalFormat df = new DecimalFormat("0.#"); /** * Construct a default OMDistance. */ public OMDistance() { super(); setRenderType(RENDERTYPE_LATLON); } /** * Create an OMDistance from a list of float lat/lon pairs. *

* NOTES: *

* * @param llPoints array of lat/lon points, arranged lat, lon, * lat, lon, etc. * @param units radians or decimal degrees. Use OMGraphic.RADIANS * or OMGraphic.DECIMAL_DEGREES * @param lType line type, from a list defined in OMGraphic. */ public OMDistance(float[] llPoints, int units, int lType, Length distanceUnits) { this(llPoints, units, lType, -1, distanceUnits); } /** * Create an OMDistance from a list of float lat/lon pairs. *

* NOTES: *

* * @param llPoints array of lat/lon points, arranged lat, lon, * lat, lon, etc. * @param units radians or decimal degrees. Use OMGraphic.RADIANS * or OMGraphic.DECIMAL_DEGREES * @param lType line type, from a list defined in OMGraphic. * @param nsegs number of segment points (only for * LINETYPE_GREATCIRCLE or LINETYPE_RHUMB line types, and if < * 1, this value is generated internally) */ public OMDistance(float[] llPoints, int units, int lType, int nsegs, Length distanceUnits) { super(llPoints, units, lType, nsegs); setDistUnits(distanceUnits); } /** * Set the Length object used to represent distances. */ public void setDistUnits(Length distanceUnits) { distUnits = distanceUnits; } /** * Get the Length object used to represent distances. */ public Length getDistUnits() { return distUnits; } public void setLocation(float[] llPoints, int units) { this.units = OMGraphic.RADIANS; if (units == OMGraphic.DECIMAL_DEGREES) { ProjMath.arrayDegToRad(llPoints); } rawllpts = llPoints; setNeedToRegenerate(true); setRenderType(RENDERTYPE_LATLON); } public void createLabels() { labels.clear(); points.clear(); if (rawllpts == null) { return; } if (rawllpts.length < 4) { return; } Geo lastGeo = Geo.createGeo(rawllpts[0], rawllpts[1]); points.add(new OMPoint(ProjMath.radToDeg(rawllpts[0]), ProjMath.radToDeg(rawllpts[1]), 1)); int l = 0; float cumulativeDist = 0f; for (int p = 2 ; p< rawllpts.length; p +=2) { Geo curGeo = Geo.createGeo(rawllpts[p], rawllpts[p+1]); float dist = getDist(lastGeo, curGeo); cumulativeDist += dist; labels.add(createLabel(lastGeo, curGeo, dist, cumulativeDist, distUnits)); points.add(new OMPoint(ProjMath.radToDeg(rawllpts[p]), ProjMath.radToDeg(rawllpts[p+1]), 1)); lastGeo = curGeo; } } /** * Get an OMText label for a segments between the given * lat/lon points whose given distance and * cumulative distance is specified. */ public OMText createLabel(Geo g1, Geo g2, float dist, float cumulativeDist, Length distanceUnits) { Geo mid; switch (getLineType()) { case LINETYPE_STRAIGHT: float lat = (float)(g1.getLatitude() + g2.getLatitude()) / 2f; float lon = (float)(g1.getLongitude() + g2.getLongitude()) / 2f; mid = new Geo(lat, lon); case LINETYPE_RHUMB: System.err.println("Rhumb distance calculation not implemented."); case LINETYPE_GREATCIRCLE: case LINETYPE_UNKNOWN: default: mid = g1.midPoint(g2); } // String text = ((int)dist) + " (" + ((int)cumulativeDist) + ")"; String text = (df.format(distanceUnits.fromRadians(dist))) + " (" + (df.format(distanceUnits.fromRadians(cumulativeDist))) + ") " + distanceUnits.getAbbr(); OMText omtext = new OMText((float)mid.getLatitude(), (float)mid.getLongitude(), text, OMText.JUSTIFY_LEFT); // omtext.setLinePaint(new Color(200, 200, 255)); return omtext; } /** * Return the distance between that lat/lons defined in radians. * The returned value is in radians. */ public float getDist(Geo g1, Geo g2) { switch (getLineType()) { case LINETYPE_STRAIGHT: float lonDist = ProjMath.lonDistance((float)g2.getLongitude(), (float)g1.getLongitude()); float latDist = (float)g2.getLatitude() - (float)g1.getLatitude(); return (float)Math.sqrt(lonDist*lonDist + latDist*latDist); case LINETYPE_RHUMB: Debug.error("Rhumb distance calculation not implemented."); case LINETYPE_GREATCIRCLE: case LINETYPE_UNKNOWN: default: return (float)g1.distance(g2); } } /** * Prepare the poly for rendering. * * @param proj Projection * @return true if generate was successful */ public boolean generate(Projection proj) { boolean ret = super.generate(proj); createLabels(); labels.generate(proj); points.generate(proj); return ret; } /** * Paint the poly. * This works if generate() has been successful. * * @param g java.awt.Graphics to paint the poly onto. */ public void render(Graphics g) { super.render(g); labels.setLinePaint(getLinePaint()); points.setLinePaint(getLinePaint()); points.setFillPaint(getLinePaint()); labels.render(g); points.render(g); } /* CTM */ private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); stream.writeObject(distUnits.getAbbr()); // or stream.writeObject(distUnits.toString()); } private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); distUnits = Length.get((String)stream.readObject()); } }