/* * Licensed Materials - Property of Perforce Software, Inc. * © Copyright Perforce Software, Inc. 2014, 2021 * © Copyright IBM Corp. 2009, 2014 * © Copyright ILOG 1996, 2009 * All Rights Reserved. * * Note to U.S. Government Users Restricted Rights: * The Software and Documentation were developed at private expense and * are "Commercial Items" as that term is defined at 48 CFR 2.101, * consisting of "Commercial Computer Software" and * "Commercial Computer Software Documentation", as such terms are * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4, * as applicable. */ package simulation; //import ilog.views.maps.defense.symbology.app6a.IlvApp6aSymbol; import ilog.views.IlvPoint; import ilog.views.graphic.IlvPolyPoints; import ilog.views.maps.IlvGeodeticComputation; import ilog.views.maps.projection.IlvEllipsoid; import ilog.views.sdm.IlvSDMEngine; /** * Class for enemy unit being targets of missiles. * * @see Mobile * */ public class PathConstrainedMobile extends Mobile { private IlvPolyPoints path; private int segmentIndex; private double distance; private double distanceToSegment; /** * Creates a target with a different symboloc tag. * * @param tag * * @param sym * symbology. * @param road * @param randomLocation */ protected PathConstrainedMobile(String tag, IlvSDMEngine sym, IlvPolyPoints road, boolean randomLocation) { super(tag, sym); this.path = road; int index = 0; if (randomLocation) { index = (int) (SimulationContext.random() * (road.getPointsCardinal() - 1)); } double lon0 = road.getPointAt(index, null).getX(); double lat0 = road.getPointAt(index, null).getY(); segmentIndex = index; distance = 0; for (int i = 0; i < segmentIndex; i++) { IlvPoint current = path.getPointAt(i, null); IlvPoint next = path.getPointAt(i + 1, null); double dy = next.getY() - current.getY(); double dx = next.getX() - current.getX(); double segmentLength = Math.sqrt(dx * dx + dy * dy); distance += segmentLength; } distanceToSegment = distance; setLocation(symbol, null, lon0, lat0); updateLocation(); } private IlvPoint computeCoordinatesFromDistance(double dist) { IlvPoint result = null; int segmentCount = path.getPointsCardinal() - 1; double remainingDistance = -1; for (int i = segmentIndex; i < segmentCount; i++) { remainingDistance = dist - distanceToSegment; IlvPoint current = path.getPointAt(i, null); IlvPoint next = path.getPointAt(i + 1, null); double dy = next.getY() - current.getY(); double dx = next.getX() - current.getX(); double segmentLength = Math.sqrt(dx * dx + dy * dy); if (remainingDistance < segmentLength) { // interpolate double alpha = remainingDistance / segmentLength; double x = current.getX() + alpha * dx; double y = current.getY() + alpha * dy; result = new IlvPoint(x, y); break; } distanceToSegment += segmentLength; segmentIndex++; } return result; } Override public void updateLocation() { if (isWrecked()) { return; } double olon = getLongitude(symbol); double olat = getLatitude(symbol); long updateTime = System.currentTimeMillis(); double dt; if (!paused) { if (lastUpdateTime == 0) { dt = 0; } else { dt = (updateTime - lastUpdateTime) / 1000.0; } dt *= SimulationContext.getTimeAcceleration(); // distance ran. double speed = getHorizontalSpeed(); double distMeter = dt * speed; // approximate distance IlvGeodeticComputation gc = new IlvGeodeticComputation(IlvEllipsoid.SPHERE); gc.setLatitude1(olat); gc.setLongitude1(olon); gc.setDistance(distMeter); gc.setForwardAzimuth(getDirection()); gc.computeGeodeticForward(); double newLon = gc.getLongitude2(); double newLat = gc.getLatitude2(); double dLat = newLat - olat; double dLon = newLon - olon; double distLonLat = Math.sqrt(dLat * dLat + dLon * dLon); distance += distLonLat; // compute new coordinates on the path IlvPoint p = computeCoordinatesFromDistance(distance); if (p == null) { wreck(); return; } // set direction IlvPoint current = path.getPointAt(segmentIndex, null); IlvPoint next = path.getPointAt(segmentIndex + 1, null); double dir = Math.atan2(next.getX() - current.getX(), next.getY() - current.getY()); setDirection(dir); setSymbolProperty(MODIFIER_DIRECTION_OF_MOVEMENT_INDICATOR, "" + Math.toDegrees(getDirection() - Math.PI / 2), //$NON-NLS-1$ false); lastUpdateTime = updateTime; // update location boolean ia = symbology.getModel().isAdjusting(); if (!ia) symbology.getModel().setAdjusting(true); setLocation(symbol, symbology, p.getX(), p.getY()); if (!ia) symbology.getModel().setAdjusting(false); } lastUpdateTime = updateTime; updateStatus(); } }