@Override public void setLayers(Layers parent) { // ok, we've been pasted. just double check that our children know who is // the boss Enumeration<Editable> numer = getSegments().elements(); while (numer.hasMoreElements()) { Editable editable = (Editable) numer.nextElement(); PlanningSegment seg = (PlanningSegment) editable; seg.setWrapper(this); } }
@Override double getMinuteDelta(PlanningSegment seg) { // how far will we travel in time? double metresPerSec = seg.getSpeed().getValueIn(WorldSpeed.M_sec); double metresPerMin = metresPerSec * 60d; double distanceM = metresPerSec * getSecsTravelled(seg); WorldDistance wd = new WorldDistance(distanceM, WorldDistance.METRES); seg.setDistanceSilent(new WorldDistance(wd.getValueIn(WorldDistance.NM), WorldDistance.NM)); return metresPerMin; }
@Override protected double getSecsTravelled(PlanningSegment seg) { // how long does it take to travel this distance? double secsTaken = seg.getDistance().getValueIn(WorldDistance.METRES) / seg.getSpeed().getValueIn(WorldSpeed.M_sec); // sort out the leg length seg.setDurationSilent(new Duration(secsTaken, Duration.SECONDS)); return secsTaken; }
public void recalculate() { Enumeration<Editable> numer = getSegments().elements(); WorldLocation thisOrigin = getOrigin(); HiResDate thisDate = getStartDate(); while (numer.hasMoreElements()) { Editable editable = (Editable) numer.nextElement(); PlanningSegment seg = (PlanningSegment) editable; PlanningCalc theCalc = null; int model = seg.getCalculation(); switch (model) { case PlanningLegCalcModelPropertyEditor.RANGE_SPEED: theCalc = new FromRangeSpeed(); break; case PlanningLegCalcModelPropertyEditor.RANGE_TIME: theCalc = new FromRangeTime(); break; case PlanningLegCalcModelPropertyEditor.SPEED_TIME: theCalc = new FromSpeedTime(); break; } // see if this is the closing segment if (seg instanceof ClosingSegment) { // what's the range and bearing back to the origin WorldVector offset = getOrigin().subtract(thisOrigin); // and store it. seg.setSpeedSilent(new WorldSpeed(12, WorldSpeed.Kts)); seg.setDistanceSilent(new WorldDistance(offset.getRange(), WorldDistance.DEGS)); seg.setCourseSilent(MWC.Algorithms.Conversions.Rads2Degs(offset.getBearing())); seg.setDepthSilent(new WorldDistance(offset.getDepth(), WorldDistance.METRES)); } theCalc.construct(seg, thisOrigin, thisDate); // did we generate anything? if (seg.size() > 0) { // ok, now update the date/location thisOrigin = seg.last().getBounds().getCentre(); thisDate = seg.endDTG(); } } // ok, sort out the symbol & label freq HiResDate symFreq = this.getSymbolFrequency(); HiResDate labelFreq = this.getLabelFrequency(); this.setSymbolFrequency(new HiResDate(0)); this.setLabelFrequency(new HiResDate(0)); // and restore them setSymbolFrequency(symFreq); setLabelFrequency(labelFreq); }
@Override public void findNearestHotSpotIn( Point cursorPos, WorldLocation cursorLoc, ComponentConstruct currentNearest, Layer parentLayer) { // initialise thisDist, since we're going to be over-writing it WorldDistance thisDist = new WorldDistance(0, WorldDistance.DEGS); Enumeration<Editable> numer = getSegments().elements(); while (numer.hasMoreElements()) { final PlanningSegment thisSeg = (PlanningSegment) numer.nextElement(); if (thisSeg.getVisible()) { // produce a location for the end FixWrapper endFix = (FixWrapper) thisSeg.last(); if (endFix != null) { // how far away is it? thisDist = endFix.getLocation().rangeFrom(cursorLoc, thisDist); final WorldLocation fixLocation = new WorldLocation(endFix.getLocation()) { private static final long serialVersionUID = 1L; @Override public void addToMe(WorldVector delta) { super.addToMe(delta); // so, what's the bearing back to the leg start? double newBearing = super.bearingFrom(thisSeg.first().getBounds().getCentre()); newBearing = MWC.Algorithms.Conversions.Rads2Degs(newBearing); // limit the bearing to the nearest 5 deg marker int m = ((int) newBearing / 10); newBearing = m * 10d; // trim it to being positive if (newBearing < 0) newBearing += 360; thisSeg.setCourse(newBearing); } }; // try range currentNearest.checkMe(this, thisDist, null, parentLayer, fixLocation); } } } }
@Override double getMinuteDelta(PlanningSegment seg) { // home long to travel along it (secs) double travelSecs = seg.getDuration().getValueIn(Duration.SECONDS); double metresPerSec = seg.getDistance().getValueIn(WorldDistance.METRES) / travelSecs; double metresPerMin = metresPerSec * 60d; // update the speed, so it makes sense in the fix WorldSpeed speedMtrs = new WorldSpeed(metresPerSec, WorldSpeed.M_sec); WorldSpeed speedKTs = new WorldSpeed(speedMtrs.getValueIn(WorldSpeed.Kts), WorldSpeed.Kts); seg.setSpeedSilent(speedKTs); return metresPerMin; }
@Override public void add(Editable point) { if (point instanceof PlanningSegment) { // hey, is this a closing segment? if (point instanceof ClosingSegment) { // do we already have one? if (this.getSegments().last() instanceof ClosingSegment) { // skip.... _toolParent.logError(ToolParent.WARNING, "Already have closing segment", null); } } // take a copy of the name, to stop it getting manmgled String name = point.getName(); super.add(point); if (point.getName() != name) ((PlanningSegment) point).setName(name); // better do a recalc, aswell recalculate(); } else { throw new RuntimeException("can't add this type to a composite track wrapper"); } }
void construct(PlanningSegment seg, WorldLocation origin, HiResDate date) { // check we have some data if (date == null || origin == null) return; double timeTravelledMillis = getSecsTravelled(seg) * 1000; // ditch the existing items seg.removeAllElements(); // ok build for this segment double courseDegs = seg.getCourse(); double courseRads = MWC.Algorithms.Conversions.Degs2Rads(courseDegs); long timeMillis = date.getDate().getTime(); final long timeStepMillis; final long ONE_MIN = 60 * 1000; final long ONE_HOUR = 60 * ONE_MIN; final long ONE_DAY = 24 * ONE_HOUR; // use a time step appropriate to how long we're generating the track for if (timeTravelledMillis <= 4 * ONE_HOUR) timeStepMillis = ONE_MIN; else if (timeTravelledMillis <= 12 * ONE_HOUR) timeStepMillis = 10 * ONE_MIN; else if (timeTravelledMillis <= 2 * ONE_DAY) timeStepMillis = 30 * ONE_MIN; else timeStepMillis = ONE_HOUR; // now work out how far he will have travelled in a time step double distPerMinute = getMinuteDelta(seg); double distPerStep = distPerMinute * (timeStepMillis / ONE_MIN); WorldVector vec = new WorldVector(courseRads, new WorldDistance(distPerStep, WorldDistance.METRES), null); for (long tNow = timeMillis; tNow <= timeMillis + timeTravelledMillis; tNow += timeStepMillis) { HiResDate thisDtg = new HiResDate(tNow); // ok, do this fix Fix thisF = new Fix(thisDtg, origin, courseRads, seg.getSpeed().getValueIn(WorldSpeed.ft_sec) / 3); // override the depth thisF.getLocation().setDepth(seg.getDepth().getValueIn(WorldDistance.METRES)); FixWrapper fw = new FixWrapper(thisF); fw.setColor(seg.getColor()); // and store it seg.add(fw); // reset the name, we're not going to use a human generated one fw.resetName(); // produce a new position origin = origin.add(vec); } }
@FireExtended public void appendReverse() { // ok, get the legs SegmentList list = super.getSegments(); ArrayList<PlanningSegment> holder = new ArrayList<PlanningSegment>(); Enumeration<Editable> iterator = list.elements(); while (iterator.hasMoreElements()) { // put this element at the start holder.add(0, (PlanningSegment) iterator.nextElement()); } // now run the legs back in reverse Iterator<PlanningSegment> iter2 = holder.iterator(); while (iter2.hasNext()) { PlanningSegment pl = iter2.next(); try { PlanningSegment pl2 = (PlanningSegment) pl.clone(); // now reverse it double newCourse = pl2.getCourse() + 180d; if (newCourse > 360) newCourse -= 360; pl2.setCourse(newCourse); // show the name as reversed pl2.setName(pl2.getName() + "(R)"); // ok, now add it this.add(pl2); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } // ok, better throw in a recalculate this.recalculate(); }
@Override protected double getSecsTravelled(PlanningSegment seg) { return seg.getDuration().getValueIn(Duration.SECONDS); }
@Override double getMinuteDelta(PlanningSegment seg) { // find out how far it travels double distPerMinute = seg.getSpeed().getValueIn(WorldSpeed.M_sec) * 60d; return distPerMinute; }