/// <summary> /// Returns the distance to the nearest point of a polygon. If the point is in the Poly, should return 0 /// </summary> /// <param name="poly"></param> /// <param name="point"></param> /// <returns></returns> public static Vec2D ClosestPointOnPolygon(Polygon2D poly, Vec2D point) { double result = 999999; double curResult = 999999; Vec2D BestPoint = null, curPoint; Vec2D one, two, zero; zero = new Vec2D(point); for (int i = 0; i < poly.xPoints.Count - 1; i++) { //calculate [i]:[1+1] one = new Vec2D(poly.xPoints[i], poly.yPoints[i]); two = new Vec2D(poly.xPoints[i + 1], poly.yPoints[i + 1]); curPoint = ClosestPointOnLineSegment(zero, one, two); curResult = zero.ScalerDistanceTo(curPoint); if (result > curResult) { result = curResult; //do we save the point where they intersect? BestPoint = curPoint; } } //then [Count-1]:[0] one = new Vec2D(poly.xPoints[poly.xPoints.Count - 1], poly.yPoints[poly.xPoints.Count - 1]); two = new Vec2D(poly.xPoints[0], poly.yPoints[0]); curPoint = ClosestPointOnLineSegment(zero, one, two); curResult = zero.ScalerDistanceTo(curPoint); if (result > curResult) { result = curResult; //do we save the point where they intersect? BestPoint = curPoint; } return(BestPoint); }
public static double DistanceFromPointToSegment(Vec2D p, Vec2D s0, Vec2D s1) {/* * Vec2D v = s0.VectorDistanceTo(s1); * Vec2D w = s0.VectorDistanceTo(p); * * double c1 = VectorDotProduct(w, v); * if (c1 <= 0) * return p.ScalerDistanceTo(s0);// d(P, S.P0); * * double c2 = VectorDotProduct(v, v); * if (c2 <= c1) * return p.ScalerDistanceTo(s1);// d(P, S.P1); * * double b = c1 / c2; * Vec2D Pb = s0.Add(v.Multiply(b));// S.P0 + b * v; */ Vec2D Pb = ClosestPointOnLineSegment(p, s0, s1); return(p.ScalerDistanceTo(Pb));// d(P, Pb); }
private List<Vec2D> MakeLocationsForGroup(T_Groupings grouping, int numPirates, List<PolygonValue> entryRegions) { //For two groupings, just return all the entry regions. We'll probably get a good distribution. if (grouping == T_Groupings.Two) return MakeLocationsInEntryRegions(numPirates, entryRegions); //For one groupings, pick a random entry region to start the group. PolygonValue entryRegion = entryRegions.ElementAt(random.Next(entryRegions.Count)); List<PolygonValue> acceptableEntryRegions = new List<PolygonValue>(); foreach (PolygonValue region in entryRegions) { Vec2D pointFromNewRegion = new Vec2D(region.points.ElementAt(0).X, region.points.ElementAt(0).Y); Vec2D pointFromFirstRegion = new Vec2D(entryRegion.points.ElementAt(0).X, entryRegion.points.ElementAt(0).Y); if (pointFromNewRegion.ScalerDistanceTo(pointFromFirstRegion) < oneGroupingDistance) { acceptableEntryRegions.Add(region); } } return MakeLocationsInEntryRegions(numPirates, acceptableEntryRegions); }
/// <summary> /// Returns a list of entry regions in which new pirates can be added while satisfying grouping constraints, given a group of existing pirates. /// </summary> /// <param name="grouping">Grouping constraints</param> /// <param name="group">Group of existing pirates</param> /// <param name="entryRegions">All avilable entry regions</param> /// <returns></returns> private List<PolygonValue> GetMatchingEntryRegions(T_Groupings grouping, List<DDDAdapter.SeamateObject> group, List<PolygonValue>entryRegions) { List<PolygonValue> matchingEntryRegions = new List<PolygonValue>(); //One grouping: matching entry regions must be within certain distance of every individual vessel in group if (grouping == T_Groupings.One) { foreach (PolygonValue region in entryRegions) { Vec2D regionPoint = new Vec2D(region.points.ElementAt(0).X, region.points.ElementAt(0).Y); bool matching = true; foreach (DDDAdapter.SeamateObject vessel in group) { Vec2D vesselPoint = new Vec2D(vessel.Location); if (vesselPoint.ScalerDistanceTo(regionPoint) > oneGroupingDistance) { matching = false; break; } } if (matching) matchingEntryRegions.Add(region); } return matchingEntryRegions; } //Two grouping: any entry region will do, the existing group satisfies constraint else return entryRegions; }
/// <summary> /// Calculates an intercept course for all pirates /// </summary> /// <param name="currentItem"></param> /// <param name="dmID"></param> public override void Generate(T_Item currentItem, String dmID) { Dictionary<T_Move, T_Reveal> dict = GetActionsAsDictionary(currentItem.Action); //Make new dictionaries; they will be copies containing either merchants or pirates Dictionary<T_Move, T_Reveal> merchantsDict = new Dictionary<T_Move,T_Reveal>(); Dictionary<T_Move, T_Reveal> piratesDict = new Dictionary<T_Move, T_Reveal>(); //Copy pirates and merchants into dictionaries foreach (T_Move key in dict.Keys) { if (GetOwner(key, dict[key]) == "Pirate DM") piratesDict.Add(key, dict[key]); else merchantsDict.Add(key, dict[key]); } if (piratesDict.Keys.Count == 0) return; //This dictionary of pirates is the one we'll use to save intercept courses. Dictionary<T_Move, T_Reveal> piratesWithInterceptCourse = new Dictionary<T_Move, T_Reveal>(); //Set each pirate on the shortest intercept course to a newly revealed or existing merchant. foreach (T_Move pirateMove in piratesDict.Keys) { Vec2D pirateLocation = new Vec2D(GetLocation(pirateMove, piratesDict[pirateMove])); //=========Check newly revealed merchants created in this item to find closest ===========================// double timeToIntercept = 1000000000000000; Vec2D closestInterceptPoint = null; T_Move closestNewMerchant = null; foreach (T_Move merchantMove in merchantsDict.Keys) { double merchantSpeed = merchantMove.Throttle * GetMaxSpeed(merchantMove); Vec2D merchantStart = new Vec2D(GetLocation(merchantMove, merchantsDict[merchantMove])); Vec2D merchantDestination = new Vec2D((LocationValue)merchantMove.Location.Item); Vec2D interceptPoint = GetInterceptPoint(merchantStart, merchantDestination, merchantSpeed, pirateLocation, GetMaxSpeed(pirateMove)); double merchantTimeToIntercept = merchantStart.ScalerDistanceTo(interceptPoint) / merchantSpeed; if (merchantTimeToIntercept < timeToIntercept) { closestNewMerchant = merchantMove; closestInterceptPoint = interceptPoint; timeToIntercept = merchantTimeToIntercept; } } //============Check merchants already revealed, see if one is closer ======================== //TODO: make sure any merchants we will move in this round are not being compared DDDAdapter.SeamateObject closestRevealedMerchant = null; foreach (DDDAdapter.SeamateObject vessel in revealedSeaVessels) { //Compare all the existing merchants' positions to see if they are closer. //if (vessel.ID == closestNewMerchant.ID) continue; if (vessel.Owner == "Merchant DM") { double merchantSpeed = vessel.Throttle * vessel.MaximumSpeed; Vec2D merchantStart = new Vec2D(vessel.Location); Vec2D merchantDestination = new Vec2D(vessel.DestinationLocation); Vec2D interceptPoint = GetInterceptPoint(merchantStart, merchantDestination, merchantSpeed, pirateLocation, GetMaxSpeed(pirateMove)); double merchantTimeToIntercept = merchantStart.ScalerDistanceTo(interceptPoint) / merchantSpeed; if (merchantTimeToIntercept < timeToIntercept) { closestNewMerchant = null; closestRevealedMerchant = vessel; closestInterceptPoint = interceptPoint; timeToIntercept = merchantTimeToIntercept; } } else continue; //ignore pirates or fleet ships } if (closestInterceptPoint == null) { return; } //Make a new move for the pirate, containing the pirate's intercept course. T_Move moveWithInterceptCourse = new T_Move(); moveWithInterceptCourse.ID = pirateMove.ID; moveWithInterceptCourse.Throttle = 1.0; moveWithInterceptCourse.Location = new T_Location(); moveWithInterceptCourse.Location.Item = closestInterceptPoint.ToLocationValue(); //Set the pirate and merchant's "Intent" relating to the intercept in their SimObjects if (closestNewMerchant != null) { ddd.UpdateObjectAttribute(closestNewMerchant.ID, "Intent", "Being intercepted:" + pirateMove.ID + ":" + timeToIntercept, "AGENT"); //Merchant ddd.UpdateObjectAttribute(pirateMove.ID, "Intent", "Intercepting:" + closestNewMerchant.ID + ":" + timeToIntercept, "AGENT"); //Pirate } else if (closestRevealedMerchant != null) { ddd.UpdateObjectAttribute(closestRevealedMerchant.ID, "Intent", "Being intercepted:" + pirateMove.ID + ":" + timeToIntercept, "AGENT"); //Merchant ddd.UpdateObjectAttribute(pirateMove.ID, "Intent", "Intercepting:" + closestRevealedMerchant.ID + ":" + timeToIntercept, "AGENT"); //Pirate } else Console.Error.WriteLine("Fix intercept generator"); //Add the pirate's updated move and reveal to pirate dictionary. piratesWithInterceptCourse[moveWithInterceptCourse] = piratesDict[pirateMove]; } //Add altered pirates back to merchants, and reset the action array. currentItem.Action = GetActionsFromDictionary(merchantsDict.Concat(piratesWithInterceptCourse).ToDictionary(kvp => kvp.Key, kvp => kvp.Value)); }
/// <summary> /// Returns the distance to the nearest point of a polygon. If the point is in the Poly, should return 0 /// </summary> /// <param name="poly"></param> /// <param name="point"></param> /// <returns></returns> public static Vec2D ClosestPointOnPolygon(Polygon2D poly, Vec2D point) { double result = 999999; double curResult = 999999; Vec2D BestPoint = null, curPoint; Vec2D one, two, zero; zero = new Vec2D(point); for (int i = 0; i < poly.xPoints.Count - 1; i++) { //calculate [i]:[1+1] one = new Vec2D(poly.xPoints[i], poly.yPoints[i]); two = new Vec2D(poly.xPoints[i + 1], poly.yPoints[i + 1]); curPoint = ClosestPointOnLineSegment(zero, one, two); curResult = zero.ScalerDistanceTo(curPoint); if (result > curResult) { result = curResult; //do we save the point where they intersect? BestPoint = curPoint; } } //then [Count-1]:[0] one = new Vec2D(poly.xPoints[poly.xPoints.Count - 1], poly.yPoints[poly.xPoints.Count - 1]); two = new Vec2D(poly.xPoints[0], poly.yPoints[0]); curPoint = ClosestPointOnLineSegment(zero, one, two); curResult = zero.ScalerDistanceTo(curPoint); if (result > curResult) { result = curResult; //do we save the point where they intersect? BestPoint = curPoint; } return BestPoint; }
public static double DistanceFromPointToSegment(Vec2D p, Vec2D s0, Vec2D s1) {/* Vec2D v = s0.VectorDistanceTo(s1); Vec2D w = s0.VectorDistanceTo(p); double c1 = VectorDotProduct(w, v); if (c1 <= 0) return p.ScalerDistanceTo(s0);// d(P, S.P0); double c2 = VectorDotProduct(v, v); if (c2 <= c1) return p.ScalerDistanceTo(s1);// d(P, S.P1); double b = c1 / c2; Vec2D Pb = s0.Add(v.Multiply(b));// S.P0 + b * v; */ Vec2D Pb = ClosestPointOnLineSegment(p, s0, s1); return p.ScalerDistanceTo(Pb);// d(P, Pb); }