void DrawLineOutline(Vector3[] worldPoints, List <Node> nodeList, float width, float additionalWidth, Color color) { Vector3 cameraPosition = SceneView.currentDrawingSceneView.camera.transform.position; for (int i = 0; i <= worldPoints.Length - 2; i++) { if (!nodeList[i].Active) { continue; } float lineWidth = width + additionalWidth; if (nodeList[i].OverrideWidth) { lineWidth = nodeList[i].CustomWidth / 2f + additionalWidth; } float distance = Vector3.Distance(worldPoints[i], cameraPosition); if (distance < 200) { List <Vector3> pointList = new List <Vector3> { worldPoints[i], worldPoints[i + 1] }; List <Vector3> newInflatedList = PolygonUtility.InflatePolygon(pointList, lineWidth, false); PolygonUtility.AlignPointsWithTerrain(newInflatedList, true, VegetationMaskLine.GroundLayerMask); Handles.color = color; Handles.DrawAAPolyLine(3, newInflatedList.ToArray()); } } }
//this checks a polylist for abnormal polys and returns only those which deem fit internal static List <Polygon2d> CheckAndCleanPolygon2dList(List <Polygon2d> polyList) { if (!CheckPolyList(polyList)) { return(null); } List <Polygon2d> cleanPolyList = new List <Polygon2d>(); for (int i = 0; i < polyList.Count; i++) { bool lineLength = true; if (!CheckPoly(polyList[i])) { continue; } if (polyList[i].Lines == null || polyList[i].Lines.Count == 0) { continue; } for (int j = 0; j < polyList[i].Lines.Count; j++) { if (polyList[i].Lines[j].Length < 0.01 && PolygonUtility.AreaPolygon(polyList[i]) < 0.2) { lineLength = false; } } if (CheckPoly(polyList[i]) && lineLength) { cleanPolyList.Add(polyList[i]); } } return(cleanPolyList); }
internal static bool CheckPolyAdjacencyToPolyList(Polygon2d poly, List <Polygon2d> polyList) { if (!CheckPoly(poly)) { return(false); } if (!CheckPolyList(polyList)) { return(false); } bool check = false; for (int i = 0; i < polyList.Count; i++) { Dictionary <string, object> adjObject = PolygonUtility.FindPolyAdjacentEdge(poly, polyList[i]); check = (bool)adjObject["Neighbour"]; } if (check) { return(true); } else { return(false); } }
//sorts a list of points form a polyline public static List <Point2d> SortPoints(List <Point2d> pointList) { if (!ValidateObject.CheckPointList(pointList)) { return(null); } Point2d cen = PolygonUtility.CentroidOfPoly(Polygon2d.ByPoints(pointList)); Vector2d vecX = new Vector2d(0, 100); List <double> angList = new List <double>(); int[] indList = new int[pointList.Count]; for (int i = 0; i < pointList.Count; i++) { Vector2d CenterToPt = new Vector2d(cen, pointList[i]); double dotValue = vecX.Dot(CenterToPt); double angValue = Math.Atan2(CenterToPt.Y - vecX.Y, CenterToPt.X - vecX.X); angList.Add(angValue); indList[i] = i; } List <int> newIndexList = new List <int>(); newIndexList = BasicUtility.SortIndex(angList); List <Point2d> sortedPointList = new List <Point2d>(); for (int i = 0; i < pointList.Count; i++) { sortedPointList.Add(pointList[newIndexList[i]]); } return(sortedPointList); }
//gets list of polygon2ds and find the most closest polygon2d to the center , to place the central stn internal static Dictionary <string, object> MakeCentralStation(List <Polygon2d> polygonsList, Point2d centerPt) { if (polygonsList == null || polygonsList.Count == 0) { return(null); } if (polygonsList.Count < 2) { return(new Dictionary <string, object> { { "PolyCentral", (polygonsList) }, { "IndexInPatientPoly", (0) } }); } List <Polygon2d> newPolyLists = new List <Polygon2d>(); List <double> distanceList = new List <double>(); double minArea = 100, ratio = 0.5, dis = 0;; int dir = 0; List <int> indices = PolygonUtility.SortPolygonsFromAPoint(polygonsList, centerPt); Polygon2d polyToPlace = polygonsList[indices[0]]; double area = PolygonUtility.AreaPolygon(polyToPlace); if (area > minArea) { List <double> spans = PolygonUtility.GetSpansXYFromPolygon2d(polyToPlace.Points); if (spans[0] > spans[1]) { dir = 1; dis = spans[0] / 2; } else { dir = 0; dis = spans[1] / 2; } Random ran = new Random(); //Dictionary<string, object> splittedPoly = BasicSplitPolyIntoTwo(polyToPlace, ratio, dir); //Dictionary<string, object> splittedPoly = SplitByDistanceFromPoint(polyToPlace, dis, dir); Dictionary <string, object> splittedPoly = SplitObject.SplitByDistance(polyToPlace, ran, dis, dir); List <Polygon2d> polyReturnedList = (List <Polygon2d>)splittedPoly["PolyAfterSplit"]; if (!ValidateObject.CheckPolyList(polyReturnedList)) { return(null); } List <int> ind = PolygonUtility.SortPolygonsFromAPoint(polyReturnedList, centerPt); newPolyLists.Add(polyReturnedList[ind[0]]); newPolyLists.Add(polyReturnedList[ind[1]]); } else { newPolyLists.Add(polyToPlace); } return(new Dictionary <string, object> { { "PolyCentral", (newPolyLists) }, { "IndexInPatientPoly", (indices[0]) } }); }
internal static Dictionary <string, object> ComputePolyCentersAlign(Polygon2d polyA, Polygon2d polyB) { //compute orig centers Point2d centerPolyA = PointUtility.CentroidInPointLists(polyA.Points); Point2d centerPolyB = PointUtility.CentroidInPointLists(polyB.Points); Point2d staticPoint, movingPoint; Polygon2d staticPoly, movingPoly; double areaPolyA = PolygonUtility.AreaPolygon(polyA); double areaPolyB = PolygonUtility.AreaPolygon(polyB); if (areaPolyA > areaPolyB) { staticPoint = centerPolyB; staticPoly = polyB; movingPoint = centerPolyA; movingPoly = polyA; } else { staticPoint = centerPolyA; staticPoly = polyA; movingPoint = centerPolyB; movingPoly = polyB; } //shift the other points Point2d movingPoint1 = new Point2d(staticPoint.X, movingPoint.Y); Point2d movingPoint2 = new Point2d(movingPoint.X, staticPoint.Y); bool IsMovingPoint1 = GraphicsUtility.PointInsidePolygonTest(movingPoly, movingPoint1); bool IsMovingPoint2 = GraphicsUtility.PointInsidePolygonTest(movingPoly, movingPoint2); if (IsMovingPoint1) { movingPoint = movingPoint1; } else if (IsMovingPoint2) { movingPoint = movingPoint2; } else { staticPoint = centerPolyA; staticPoly = polyA; movingPoint = movingPoint1; movingPoly = polyB; } return(new Dictionary <string, object> { { "CenterPolyA", (staticPoint) }, { "CenterPolyB", (movingPoint) }, { "PolyA", (staticPoly) }, { "PolyB", (movingPoly) } }); }
//check if a given polygon2d has any of its longer edges aligned with any edge of the containerpolygon2d internal static bool CheckPolyGetsExternalWall(Polygon2d poly, Polygon2d containerPoly, double shortEdgeDist = 16, bool tag = true) { bool check = false; if (!ValidateObject.CheckPoly(poly)) { return(check); } Polygon2d polyReg = new Polygon2d(null); //make given polys reduce number of points if (tag) { polyReg = new Polygon2d(poly.Points); } else { polyReg = poly; } Polygon2d containerPolyReg = new Polygon2d(containerPoly.Points); for (int i = 0; i < polyReg.Points.Count; i++) { int a = i, b = i + 1; double eps = 0; if (i == polyReg.Points.Count - 1) { b = 0; } double distance = PointUtility.DistanceBetweenPoints(polyReg.Points[a], polyReg.Points[b]); List <double> spansSorted = PolygonUtility.GetPolySpan(containerPolyReg); if (distance <= spansSorted[0] * 0.75) { continue; } Line2d lineA = Line2d.ByStartPointEndPoint(polyReg.Points[a], polyReg.Points[b]); for (int j = 0; j < containerPolyReg.Points.Count; j++) { int c = j, d = j + 1; if (j == containerPolyReg.Points.Count - 1) { d = 0; } Line2d lineB = Line2d.ByStartPointEndPoint(containerPolyReg.Points[c], containerPolyReg.Points[d]); check = GraphicsUtility.LineAdjacencyCheck(lineA, lineB, eps); if (check) { break; } } if (check) { break; } } return(check); }
public static Dictionary <string, object> SplitByDistance(Polygon2d polyOutline, Random ran, double distance = 10, int dir = 0, double spacing = 0) { if (!ValidateObject.CheckPoly(polyOutline)) { return(null); } double extents = 5000, spacingProvided; List <Point2d> polyOrig = polyOutline.Points; if (spacing == 0) { spacingProvided = BuildLayout.SPACING; } else { spacingProvided = spacing; } List <Point2d> poly = PolygonUtility.SmoothPolygon(polyOrig, spacingProvided); if (!ValidateObject.CheckPointList(poly)) { return(null); } Dictionary <int, object> obj = PointUtility.PointSelector(ran, poly); Point2d pt = (Point2d)obj[0]; int orient = (int)obj[1]; Line2d splitLine = new Line2d(pt, extents, dir); // push this line right or left or up or down based on ratio if (dir == 0) { splitLine = LineUtility.Move(splitLine, 0, orient * distance); } else { splitLine = LineUtility.Move(splitLine, orient * distance, 0); } Dictionary <string, object> intersectionReturn = MakeIntersections(poly, splitLine, spacingProvided); List <Point2d> intersectedPoints = (List <Point2d>)intersectionReturn["IntersectedPoints"]; List <Polygon2d> splittedPoly = (List <Polygon2d>)intersectionReturn["PolyAfterSplit"]; List <Point2d> ptA = (List <Point2d>)intersectionReturn["PointASide"]; List <Point2d> ptB = (List <Point2d>)intersectionReturn["PointBSide"]; Polygon2d polyA = new Polygon2d(ptA, 0), polyB = new Polygon2d(ptB, 0); //List<Polygon2d> splittedPoly = new List<Polygon2d>(); //splittedPoly.Add(polyA); splittedPoly.Add(polyB); return(new Dictionary <string, object> { { "PolyAfterSplit", (splittedPoly) }, { "SplitLine", (splitLine) }, { "IntersectedPoints", (intersectedPoints) }, { "PointASide", (ptA) }, { "PointBSide", (ptB) } }); }
public static Dictionary <string, object> SplitByDistanceFromPoint(Polygon2d polyOutline, double distance = 10, int dir = 0, double space = 0) { if (polyOutline == null || polyOutline.Points == null || polyOutline.Points.Count == 0) { return(null); } if (space == 0) { space = BuildLayout.SPACING2; } double extents = 5000; int threshValue = 50; List <Point2d> polyOrig = polyOutline.Points; List <Point2d> poly = new List <Point2d>(); if (polyOrig.Count > threshValue) { poly = polyOrig; } else { poly = PolygonUtility.SmoothPolygon(polyOrig, space); } if (poly == null || poly.Count == 0) { return(null); } int lowInd = PointUtility.LowestPointFromList(poly); Point2d lowPt = poly[lowInd]; Line2d splitLine = new Line2d(lowPt, extents, dir); if (dir == 0) { splitLine = LineUtility.Move(splitLine, 0, 1 * distance); } else { splitLine = LineUtility.Move(splitLine, 1 * distance, 0); } Dictionary <string, object> intersectionReturn = MakeIntersections(poly, splitLine, space); List <Point2d> intersectedPoints = (List <Point2d>)intersectionReturn["IntersectedPoints"]; List <Polygon2d> splittedPoly = (List <Polygon2d>)intersectionReturn["PolyAfterSplit"]; List <Point2d> ptA = (List <Point2d>)intersectionReturn["PointASide"]; List <Point2d> ptB = (List <Point2d>)intersectionReturn["PointBSide"]; return(new Dictionary <string, object> { { "PolyAfterSplit", (splittedPoly) }, { "SplitLine", (splitLine) }, { "IntersectedPoints", (intersectedPoints) }, { "PointASide", (ptA) }, { "PointBSide", (ptB) } }); }
// find the closest point to a point from a group of cells internal static int FindClosestPointIndex(List <Cell> cellList, Point2d pt) { List <Point2d> ptList = new List <Point2d>(); for (int i = 0; i < cellList.Count; i++) { if (cellList[i].CellAvailable) { ptList.Add(cellList[i].CenterPoint); } } return(PolygonUtility.FindClosestPointIndex(ptList, pt)); }
/// <summary> /// Distributes random points within bounds and creates a convex hull around it. /// </summary> /// <param name="mask"></param> /// <param name="bounds"></param> /// <param name="count"></param> public static List <Vector3> CreateRandomShapeUsingConvexHull(Bounds bounds, int count) { List <Vector2> points = new List <Vector2>(); for (int i = 0; i < count; i++) { points.Add(PolygonUtils.GetRandomPointXZ(bounds)); } List <Vector2> convexHull = PolygonUtility.GetConvexHull(points); List <Vector3> nodes = convexHull.ConvertAll <Vector3>(item => new Vector3(item.x, 0, item.y)); return(nodes); }
//returns the highest and lowest point along with indices from a pointlist internal static Dictionary <string, object> ReturnHighestAndLowestPointofBBox(Polygon2d poly) { Range2d range = PolygonUtility.GetRang2DFromBBox(ReadData.FromPointsGetBoundingPoly(poly.Points)); double minX = range.Xrange.Min; double maxX = range.Xrange.Max; double minY = range.Yrange.Min; double maxY = range.Yrange.Max; Point2d lowPt = new Point2d(minX, minY), hipt = new Point2d(maxX, maxY); return(new Dictionary <string, object> { { "LowerPoint", (lowPt) }, { "HigherPoint", (hipt) }, }); }
/// <summary> /// Transform the mask and convert it into its convex hull. /// </summary> /// <param name="mask"></param> public static void ConvexHull(VegetationMaskArea mask) { Vector3 maskPosition = mask.transform.position; List <Vector2> positionsXY = mask.Nodes.ConvertAll <Vector2>(item => new Vector2(item.Position.x, item.Position.z)); List <Vector2> convexHull = PolygonUtility.GetConvexHull(positionsXY); mask.Nodes.Clear(); foreach (Vector2 nodePosition in convexHull) { mask.AddNodeToEnd(new Vector3(maskPosition.x + nodePosition.x, 0, maskPosition.z + nodePosition.y)); } // center main handle, implicitly updates the mask CenterMainHandle(mask); }
public static Dictionary <string, object> SplitByLine(Polygon2d polyOutline, Line2d inputLine, double distance = 5) { if (!ValidateObject.CheckPoly(polyOutline)) { return(null); } List <Point2d> polyOrig = polyOutline.Points; List <Point2d> poly = PolygonUtility.SmoothPolygon(polyOrig, BuildLayout.SPACING); Line2d splitLine = new Line2d(inputLine); Point2d centerPoly = PointUtility.CentroidInPointLists(poly); bool checkSide = ValidateObject.CheckPointSide(splitLine, centerPoly); int orient = ValidateObject.CheckLineOrient(splitLine); if (orient == 0) { if (!checkSide) { splitLine = LineUtility.Move(splitLine, 0, -1 * distance); } else { splitLine = LineUtility.Move(splitLine, 0, 1 * distance); } } else { if (checkSide) { splitLine = LineUtility.Move(splitLine, -1 * distance, 0); } else { splitLine = LineUtility.Move(splitLine, 1 * distance, 0); } } Dictionary <string, object> intersectionReturn = MakeIntersections(poly, splitLine, BuildLayout.SPACING); List <Polygon2d> splittedPoly = (List <Polygon2d>)intersectionReturn["PolyAfterSplit"]; return(new Dictionary <string, object> { { "PolyAfterSplit", (splittedPoly) }, { "SplitLine", (splitLine) } }); }
//sort points clockwise direction internal static List <Point2d> DoSortClockwise(List <Point2d> poly, List <Point2d> intersectedPoints, List <int> pIndex) { if (intersectedPoints == null || intersectedPoints.Count == 0) { return(null); } List <Point2d> cleanedPtList = new List <Point2d>(); if (intersectedPoints.Count > 2) { cleanedPtList = CleanDuplicatePoint2d(intersectedPoints); } else { cleanedPtList = intersectedPoints; } return(PolygonUtility.OrderPolygon2dPoints(poly, cleanedPtList, pIndex)); //intersectedPoints }
// from a list of given polys it assigns each program a list of polys till its area is satisfied internal static List <List <Polygon2d> > AssignPolysToProgramData(List <ProgramData> newProgDataList, List <Polygon2d> polygonLists) { //reset the area provided to the input progdata for (int i = 0; i < newProgDataList.Count; i++) { newProgDataList[i].ProgAreaProvided = 0; } List <List <Polygon2d> > polyEachProgramList = new List <List <Polygon2d> >(); Stack <Polygon2d> polyStack = new Stack <Polygon2d>(); for (int i = 0; i < polygonLists.Count; i++) { polyStack.Push(polygonLists[i]); } for (int i = 0; i < newProgDataList.Count; i++) { ProgramData progItem = newProgDataList[i]; //Trace.WriteLine("Starting Porg Data : " + i + "///////////"); bool added = false; //double areaProgram = progData[i].CurrentAreaNeeds; List <Polygon2d> polysForProg = new List <Polygon2d>(); while (progItem.CurrentAreaNeeds > 0 && polyStack.Count > 0) { //Trace.WriteLine(" = = now in while = = "); Polygon2d currentPoly = polyStack.Pop(); double currentArea = PolygonUtility.AreaPolygon(currentPoly); progItem.AddAreaToProg(currentArea); polysForProg.Add(currentPoly); //Trace.WriteLine("Area Given Now is : " + progItem.AreaAllocatedValue); //Trace.WriteLine("Area Left over to Add :" + progItem.CurrentAreaNeeds); added = true; } //dummy is just to make sure the function re reuns when slider is hit if (added) { polyEachProgramList.Add(polysForProg); } //if (!added) Trace.WriteLine("Did not add. PolyStack Left : " + polyStack.Count + " | Current area needs were : " + progItem.CurrentAreaNeeds); //Trace.WriteLine("++++++++++++++++++++++++++++++"); } return(polyEachProgramList); }
public static Dictionary <string, object> CheckPolyNotches(Polygon2d poly, double distance = 10) { if (!CheckPoly(poly)) { return(null); } bool hasNotches = true; int count = 0, maxTry = 2 * poly.Points.Count; Polygon2d currentPoly = new Polygon2d(poly.Points); while (hasNotches && count < maxTry) { Dictionary <string, object> notchObject = PolygonUtility.RemoveAnyNotches(currentPoly, distance); if (notchObject == null) { continue; } currentPoly = (Polygon2d)notchObject["PolyNotchRemoved"]; for (int i = 0; i < poly.Lines.Count; i++) { int a = i, b = i + 1; if (i == poly.Points.Count - 1) { b = 0; } if (poly.Lines[a].Length < distance && poly.Lines[b].Length < distance) { hasNotches = true; break; } else { hasNotches = false; } } count += 1; } return(new Dictionary <string, object> { { "PolyReduced", (poly) }, { "HasNotches", (hasNotches) }, { "Trials", (count) } }); }
/// <summary> /// Apply the Douglas Peucker reduction algorithm /// </summary> /// <param name="positions"></param> /// <returns></returns> public static List <Vector3> ApplyDoublesPeucker(List <Vector3> positions, float douglasPeuckerReductionTolerance) { if (douglasPeuckerReductionTolerance == 0) { return(positions); } // convert to vector2 List <Vector2> vector2List = positions.ConvertAll <Vector2>(item => new Vector2(item.x, item.z)); // use vspro's DouglasPeuckerReduction algorithm vector2List = PolygonUtility.DouglasPeuckerReduction(vector2List, douglasPeuckerReductionTolerance); // convert back to vector3 if (vector2List.Count >= 3) { positions = vector2List.ConvertAll <Vector3>(item => new Vector3(item.x, 0, item.y)); } return(positions); }
public void GenerateHullNodes(float tolerance) { List <Vector2> worldSpacePointList = new List <Vector2>(); MeshFilter[] mersFilters = GetComponentsInChildren <MeshFilter>(); for (int i = 0; i <= mersFilters.Length - 1; i++) { Mesh mesh = mersFilters[i].sharedMesh; if (mesh) { List <Vector3> verticeList = new List <Vector3>(); mesh.GetVertices(verticeList); for (int j = 0; j <= verticeList.Count - 1; j++) { Vector3 worldSpacePosition = mersFilters[i].transform.TransformPoint(verticeList[j]); Vector2 worldSpacePoint = new Vector2 { x = worldSpacePosition.x, y = worldSpacePosition.z }; worldSpacePointList.Add(worldSpacePoint); } } } List <Vector2> hullPointList = PolygonUtility.GetConvexHull(worldSpacePointList); List <Vector2> reducedPointList = PolygonUtility.DouglasPeuckerReduction(hullPointList, tolerance); if (reducedPointList.Count >= 3) { ClearNodes(); for (int i = 0; i <= reducedPointList.Count - 1; i++) { Vector3 worldSpacePosition = new Vector3(reducedPointList[i].x, 0, reducedPointList[i].y); AddNode(worldSpacePosition); } PositionNodes(); } }
//checks a polygon2d to have min Area and min dimensions internal static bool CheckPolyDimension(Polygon2d poly, double minArea = 6, double side = 2) { if (!CheckPoly(poly)) { return(false); } if (PolygonUtility.AreaPolygon(poly) < minArea) { return(false); } List <double> spans = PolygonUtility.GetSpansXYFromPolygon2d(poly.Points); if (spans[0] < side) { return(false); } if (spans[1] < side) { return(false); } return(true); }
//uses makepolysofproportion function to split one big poly into sub components internal static Dictionary <string, object> SplitBigPolys(List <Polygon2d> polyInputList, double acceptableWidth, double factor = 4) { List <Polygon2d> polyOrganizedList = new List <Polygon2d>(), polyCoverList = new List <Polygon2d>(); int count = 0; for (int i = 0; i < polyInputList.Count; i++) { Polygon2d poly = polyInputList[i]; if (poly == null || poly.Points == null || poly.Points.Count == 0) { count += 1; continue; } double targetArea = PolygonUtility.AreaPolygon(poly) / factor; MakePolysOfProportion(poly, polyOrganizedList, polyCoverList, acceptableWidth, targetArea); } BuildLayout.RECURSE = 0; return(new Dictionary <string, object> { { "PolySpaces", (polyOrganizedList) }, { "PolyForCirculation", (polyCoverList) } }); }
//checsk the aspect ratio of polygons internal static bool CheckPolyAspectRatio(Polygon2d poly, double minDimensionAllowed = 5) { if (!CheckPoly(poly)) { return(false); } List <double> spans = PolygonUtility.GetSpansXYFromPolygon2d(poly.Points); if (spans.Count > 1) { if (spans[0] < minDimensionAllowed || spans[1] < minDimensionAllowed) { return(false); } double aspectRatio = spans[0] / spans[1]; if (aspectRatio < 1) { aspectRatio = 1 / aspectRatio; } if (aspectRatio > 5) { return(false); } if (aspectRatio > 1.5) { double areaShouldBe = spans[0] * spans[1]; double areaPoly = PolygonUtility.AreaPolygon(poly); if (areaPoly / areaShouldBe < 0.9) { return(false); } } } return(true); }
public static Dictionary <string, object> MakeProgCirculationPolys(List <Line2d> circulationNetwork, List <Polygon2d> polyProgList, double circulationWidth = 8, double circulationFrequency = 0.5, int designSeed = 10) { if (!ValidateObject.CheckPolyList(polyProgList)) { return(null); } if (circulationNetwork == null || circulationNetwork.Count == 0) { return(null); } List <Line2d> flatLineList = new List <Line2d>(); List <bool> IsDuplicateList = new List <bool>(); polyProgList = PolygonUtility.SmoothPolygonList(polyProgList, 5); //flatten all the polys in each depts to make it one list List <Polygon2d> circulationPolyList = new List <Polygon2d>(); List <Polygon2d> updatedProgPolyList = new List <Polygon2d>(); List <int> deptIdList = new List <int>(); double allowedCircRatio = 4; List <double> areaProgPolyList = new List <double>(); for (int i = 0; i < polyProgList.Count; i++) { areaProgPolyList.Add(PolygonUtility.AreaPolygon(polyProgList[i])); } double maxArea = areaProgPolyList.Max(); areaProgPolyList.Sort(); int value = (int)(areaProgPolyList.Count / 3); double areaThresh = areaProgPolyList[value]; Random ran = new Random(designSeed); for (int i = 0; i < circulationNetwork.Count; i++) { Line2d splitter = circulationNetwork[i]; double someNumber = BasicUtility.RandomBetweenNumbers(ran, 1, 0); if (someNumber > circulationFrequency) { continue; } for (int j = 0; j < polyProgList.Count; j++) { Polygon2d progPoly = polyProgList[j]; double areaPoly = PolygonUtility.AreaPolygon(progPoly); Point2d midPt = LineUtility.LineMidPoint(splitter); Point2d nudgedMidPt = LineUtility.NudgeLineMidPt(splitter, progPoly, 0.5); bool checkInside = GraphicsUtility.PointInsidePolygonTest(progPoly, nudgedMidPt); if (checkInside) { Dictionary <string, object> splitResult = SplitObject.SplitByLine(progPoly, splitter, circulationWidth); List <Polygon2d> polyAfterSplit = (List <Polygon2d>)(splitResult["PolyAfterSplit"]); if (ValidateObject.CheckPolyList(polyAfterSplit)) { double areaA = PolygonUtility.AreaPolygon(polyAfterSplit[0]), areaB = PolygonUtility.AreaPolygon(polyAfterSplit[1]); if (areaA < areaB) { if (polyAfterSplit[0].Points != null) { if (ValidateObject.CheckPolyBBox(polyAfterSplit[0], allowedCircRatio)) { circulationPolyList.Add(polyAfterSplit[0]); } } updatedProgPolyList.Add(polyAfterSplit[1]); } else { if (polyAfterSplit[1].Points != null) { if (ValidateObject.CheckPolyBBox(polyAfterSplit[1], allowedCircRatio)) { circulationPolyList.Add(polyAfterSplit[1]); } } updatedProgPolyList.Add(polyAfterSplit[0]); } } // end of if loop checking polylist } // end of check inside } // end of for loop j } // end of for loop i return(new Dictionary <string, object> { { "ProgCirculationPoly", (circulationPolyList) } }); }
public static Dictionary <string, object> FindDeptCirculationNetwork(List <DeptData> deptData, Polygon2d leftOverPoly = null, bool noExternalWall = false, double circulationFrequency = 0.75) { if (deptData == null || deptData.Count == 0) { return(null); } double limit = 0; List <Polygon2d> polygonsAllDeptList = new List <Polygon2d>(); List <DeptData> deptDataAllDeptList = new List <DeptData>(); List <List <string> > deptNamesNeighbors = new List <List <string> >(); List <List <Line2d> > lineCollection = new List <List <Line2d> >(); //make flattened list of all dept data and dept polys for (int i = 0; i < deptData.Count; i++) { List <Polygon2d> polyList = deptData[i].PolyAssignedToDept; if (!ValidateObject.CheckPolyList(polyList)) { continue; } for (int j = 0; j < polyList.Count; j++) { polygonsAllDeptList.Add(polyList[j]); deptDataAllDeptList.Add(deptData[i]); } } if (leftOverPoly != null) { polygonsAllDeptList.Add(leftOverPoly); } //else Trace.WriteLine("leftover poly found null, so not added"); List <Line2d> networkLine = new List <Line2d>(); for (int i = 0; i < polygonsAllDeptList.Count; i++) { Polygon2d polyA = polygonsAllDeptList[i]; for (int j = i + 1; j < polygonsAllDeptList.Count; j++) { Polygon2d polyB = polygonsAllDeptList[j]; Dictionary <string, object> checkNeighbor = PolygonUtility.FindPolyAdjacentEdge(polyA, polyB, limit); if (checkNeighbor != null) { if ((bool)checkNeighbor["Neighbour"] == true) { networkLine.Add((Line2d)checkNeighbor["SharedEdge"]); } } } } // if externalWalls not necessary List <Line2d> extraLines = new List <Line2d>(); List <Polygon2d> polyKeyList = new List <Polygon2d>(); if (noExternalWall) { polyKeyList = deptData[0].PolyAssignedToDept; for (int i = 0; i < polyKeyList.Count; i++) { Polygon2d polyA = polyKeyList[i]; for (int j = i + 1; j < polyKeyList.Count; j++) { Polygon2d polyB = polyKeyList[j]; Dictionary <string, object> checkNeighbor = PolygonUtility.FindPolyAdjacentEdgeEdit(polyA, polyB, 0.05); if (checkNeighbor != null) { if ((bool)checkNeighbor["Neighbour"] == true) { networkLine.Add((Line2d)checkNeighbor["SharedEdge"]); extraLines.Add((Line2d)checkNeighbor["SharedEdge"]); } } } } } List <Line2d> cleanNetworkLines = LineUtility.RemoveDuplicateLines(networkLine); // extend the lines found for (int i = 0; i < cleanNetworkLines.Count; i++) { cleanNetworkLines[i] = LineUtility.ExtendLine(cleanNetworkLines[i], 2000); } cleanNetworkLines = RemoveNetworkRedundancy(cleanNetworkLines, circulationFrequency); //return cleanNetworkLines; return(new Dictionary <string, object> { { "CirculationNetworkLines", (cleanNetworkLines) } }); }
public static Dictionary <string, object> SplitByRatio(Polygon2d polyOutline, double ratio = 0.5, int dir = 0) { if (polyOutline == null) { return(null); } if (polyOutline != null && polyOutline.Points == null) { return(null); } double extents = 5000; double minimumLength = 2, minWidth = 10, aspectRatio = 0, eps = 0.1; List <Point2d> polyOrig = polyOutline.Points; List <Point2d> poly = PolygonUtility.SmoothPolygon(polyOrig, BuildLayout.SPACING); List <double> spans = PolygonUtility.GetSpansXYFromPolygon2d(poly); double horizontalSpan = spans[0], verticalSpan = spans[1]; Point2d polyCenter = PolygonUtility.CentroidOfPoly(Polygon2d.ByPoints(poly)); if (horizontalSpan < minimumLength || verticalSpan < minimumLength) { return(null); } if (horizontalSpan > verticalSpan) { dir = 1; aspectRatio = horizontalSpan / verticalSpan; } else { dir = 0; aspectRatio = verticalSpan / horizontalSpan; } // adjust ratio if (ratio < 0.15) { ratio = ratio + eps; } if (ratio > 0.85) { ratio = ratio - eps; } if (horizontalSpan < minWidth || verticalSpan < minWidth) { ratio = 0.5; } Line2d splitLine = new Line2d(polyCenter, extents, dir); double shift = ratio - 0.5; if (dir == 0) { splitLine = LineUtility.Move(splitLine, 0, shift * verticalSpan); } else { splitLine = LineUtility.Move(splitLine, shift * horizontalSpan, 0); } Dictionary <string, object> intersectionReturn = MakeIntersections(poly, splitLine, BuildLayout.SPACING); List <Point2d> intersectedPoints = (List <Point2d>)intersectionReturn["IntersectedPoints"]; List <Polygon2d> splittedPoly = (List <Polygon2d>)intersectionReturn["PolyAfterSplit"]; return(new Dictionary <string, object> { { "PolyAfterSplit", (splittedPoly) }, { "SplitLine", (splitLine) }, { "IntersectedPoints", (intersectedPoints) } }); }
/// <summary> /// Modifies a polygon and creates a random shape. /// /// Algorithm: /// /// * create a new polygon, subdivided this way: /// + get center of polygon /// + create a list of angles for iteration /// + iterate through the angles, create a line using the angle and find the intersection with a line of the polygon /// * iterate through the subdivided polygon /// + move the vertex towards the center /// + consider previous vertex in order to not move in too large steps /// </summary> public static List <Vector3> CreateRandomShape(List <Vector3> polygon, float ellipseRelaxationFactor, int angleStepCount, bool randomAngleMovement, bool keepOriginalShape, float douglasPeuckerReductionTolerance) { Vector3 meanVector = PolygonUtils.GetMeanVector(polygon); float length = meanVector.magnitude * 2; #region create angles // get the list of angles to step through List <float> angleRadList = CreateAngleList(angleStepCount, randomAngleMovement); #endregion create angles #region create new polygon using angles List <Vector3> subdividedPolygon = new List <Vector3>(); // add existing points in order to keep the general voronoi shape if (keepOriginalShape) { subdividedPolygon.AddRange(polygon); } for (int i = 0; i < angleRadList.Count; i++) { // convert angle from deg to rad float angle = angleRadList[i]; float x = meanVector.x + length * Mathf.Cos(angle); float z = meanVector.z + length * Mathf.Sin(angle); // position on the ellipse Vector3 line1PositionA = meanVector; Vector3 line1PositionB = new Vector3(x, 0, z); for (var j = 0; j < polygon.Count; j++) { int currIndex = j; int nextIndex = j + 1; if (nextIndex == polygon.Count) { nextIndex = 0; } Vector3 line2PositionA = new Vector3(polygon[currIndex].x, 0, polygon[currIndex].z); Vector3 line2PositionB = new Vector3(polygon[nextIndex].x, 0, polygon[nextIndex].z); Vector3 intersection = Vector3.zero; // try and find an intersection. if one is found, add the point to the list if (PolygonUtils.LineSegmentsIntersection(line1PositionA, line1PositionB, line2PositionA, line2PositionB, out intersection)) { subdividedPolygon.Add(intersection); break; } } } // sort again PolygonUtils.SortClockWise(subdividedPolygon); #endregion create new polygon using angles #region create new polygon using the intersections List <Vector3> newPolygon = new List <Vector3>(); float prevDistance = 0; for (int i = 0; i < subdividedPolygon.Count; i++) { Vector3 curr = subdividedPolygon[i]; // position on the ellipse Vector3 position = curr; // from center to position float distance = (position - meanVector).magnitude; Vector3 direction = (position - meanVector).normalized; // move from center towards new position. but not too much, let it depend on the previous distance { // move initially from 0 to max distance. otherwise use the previous value float min = i == 0 ? distance * ellipseRelaxationFactor : prevDistance * ellipseRelaxationFactor; float max = distance; // the radius must be smaller during the next iteration, we are navigating around an ellipse => clamp the values if (min > max) { min = max; } float moveDistance = UnityEngine.Random.Range(min, max); distance = moveDistance; } position = meanVector + distance * direction; newPolygon.Add(position); prevDistance = distance; } #endregion create new polygon using the intersections if (douglasPeuckerReductionTolerance > 0) { // convert to vector2 List <Vector2> vector2List = newPolygon.ConvertAll <Vector2>(item => new Vector2(item.x, item.z)); // use vspro's DouglasPeuckerReduction algorithm vector2List = PolygonUtility.DouglasPeuckerReduction(vector2List, douglasPeuckerReductionTolerance); // convert back to vector3 if (vector2List.Count >= 3) { newPolygon = vector2List.ConvertAll <Vector3>(item => new Vector3(item.x, 0, item.y)); } } return(newPolygon); }
//subdivide a given poly into smaller parts till acceptable width is met, returns list of polydept grids and list of polys to compute circulation public static List <List <Polygon2d> > SplitRecursivelyToSubdividePoly(List <Polygon2d> polyList, double acceptableWidth = 10, double circulationFreq = 10, double ratio = 0.5, bool tag = false) { if (!ValidateObject.CheckPolyList(polyList)) { return(null); } int count = 0; Queue <Polygon2d> polyQueue = new Queue <Polygon2d>(); List <List <Polygon2d> > polyAllReturn = new List <List <Polygon2d> >(); List <Polygon2d> polyBrokenList = new List <Polygon2d>(), polyCirculationList = new List <Polygon2d>(); double totalArea = 0; // cirFac = Math.Ceiling(acceptableWidth/ circulationFreq); double cirFac = circulationFreq; for (int i = 0; i < polyList.Count; i++) { totalArea += PolygonUtility.AreaPolygon(polyList[i]); polyQueue.Enqueue(polyList[i]); } Random rand = new Random(); double targetArea = totalArea / cirFac; while (polyQueue.Count > 0) { Polygon2d currentPoly = polyQueue.Dequeue(); Dictionary <string, object> splitObj = SplitByRatio(currentPoly, ratio, 0); if (tag) { ratio = BasicUtility.RandomBetweenNumbers(rand, 0.7, 0.35); } if (splitObj == null) { continue; } List <Polygon2d> polySplitList = (List <Polygon2d>)splitObj["PolyAfterSplit"]; if (ValidateObject.CheckPolyList(polySplitList) && polySplitList.Count > 1) { polySplitList = PolygonUtility.SmoothPolygonList(polySplitList, 2); Polygon2d bbox1 = Polygon2d.ByPoints(ReadData.FromPointsGetBoundingPoly(polySplitList[0].Points)); Polygon2d bbox2 = Polygon2d.ByPoints(ReadData.FromPointsGetBoundingPoly(polySplitList[1].Points)); if (!ValidateObject.CheckPoly(bbox1) || !ValidateObject.CheckPoly(bbox2)) { continue; } if (PolygonUtility.AreaPolygon(polySplitList[0]) > targetArea) { polyCirculationList.Add(polySplitList[0]); } if (PolygonUtility.AreaPolygon(polySplitList[1]) > targetArea) { polyCirculationList.Add(polySplitList[1]); } if (bbox1.Lines[0].Length < acceptableWidth || bbox1.Lines[1].Length < acceptableWidth) { polyBrokenList.Add(polySplitList[0]); } else { polyQueue.Enqueue(polySplitList[0]); } if (bbox2.Lines[0].Length < acceptableWidth || bbox2.Lines[1].Length < acceptableWidth) { polyBrokenList.Add(polySplitList[1]); } else { polyQueue.Enqueue(polySplitList[1]); } } if (ValidateObject.CheckPolyList(polySplitList) && polySplitList.Count < 2) { Polygon2d bbox1 = Polygon2d.ByPoints(ReadData.FromPointsGetBoundingPoly(polySplitList[0].Points)); if (!ValidateObject.CheckPoly(bbox1)) { continue; } if (bbox1.Lines[0].Length < acceptableWidth || bbox1.Lines[1].Length < acceptableWidth) { polyBrokenList.Add(polySplitList[0]); } if (PolygonUtility.AreaPolygon(polySplitList[0]) > targetArea) { polyCirculationList.Add(polySplitList[0]); } else { polyQueue.Enqueue(polySplitList[0]); } } count += 1; } for (int i = 0; i < polyQueue.Count; i++) { polyBrokenList.Add(polyQueue.Dequeue()); } polyAllReturn.Add(polyBrokenList); polyAllReturn.Add(polyCirculationList); return(polyAllReturn); }
//gets a poly and recursively splits it till acceptabledimension is met and makes a polyorganized list internal static void MakePolysOfProportion(Polygon2d poly, List <Polygon2d> polyOrganizedList, List <Polygon2d> polycoverList, double acceptableWidth, double targetArea) { BuildLayout.RECURSE += 1; List <double> spanListXY = PolygonUtility.GetSpansXYFromPolygon2d(poly.Points); double spanX = spanListXY[0], spanY = spanListXY[1]; double aspRatio = spanX / spanY; double lowRange = 0.3, highRange = 2; double maxValue = 0.70, minValue = 0.35; double threshDistanceX = acceptableWidth; double threshDistanceY = acceptableWidth; Random ran = new Random(); bool square = true; double div; div = BasicUtility.RandomBetweenNumbers(BuildLayout.RANGENERATE, maxValue, minValue); if (spanX > threshDistanceX && spanY > threshDistanceY) { square = false; } else { if (aspRatio > lowRange && aspRatio < highRange) { square = false; } else { square = true; } } if (square) { polyOrganizedList.Add(poly); } else { Dictionary <string, object> splitResult; //poly is rectangle so split it into two and add if (spanX > spanY) { double dis = spanY * div; int dir = 1; //splitResult = BasicSplitPolyIntoTwo(poly, 0.5, dir); splitResult = SplitObject.SplitByDistance(poly, ran, dis, dir, BuildLayout.SPACING2); //splitResult = SplitByDistanceFromPoint(poly, dis, dir); } else { double dis = spanX * div; int dir = 0; //splitResult = BasicSplitPolyIntoTwo(poly, 0.5, dir); splitResult = SplitObject.SplitByDistance(poly, ran, dis, dir, BuildLayout.SPACING2); //splitResult = SplitByDistanceFromPoint(poly, dis, dir); } List <Polygon2d> polyAfterSplit = (List <Polygon2d>)splitResult["PolyAfterSplit"]; if (ValidateObject.CheckPolyList(polyAfterSplit)) { double areaPolA = PolygonUtility.AreaPolygon(polyAfterSplit[0]); double areaPolB = PolygonUtility.AreaPolygon(polyAfterSplit[1]); if (areaPolA > targetArea) { polycoverList.Add(polyAfterSplit[0]); } if (areaPolB > targetArea) { polycoverList.Add(polyAfterSplit[1]); } List <double> spanA = PolygonUtility.GetSpansXYFromPolygon2d(polyAfterSplit[0].Points); List <double> spanB = PolygonUtility.GetSpansXYFromPolygon2d(polyAfterSplit[1].Points); //Trace.WriteLine("RECURSE is : " + RECURSE); if (BuildLayout.RECURSE < 1500) { if ((spanA[0] > 0 && spanA[1] > 0) || (spanB[0] > 0 && spanB[1] > 0)) { if (spanA[0] > acceptableWidth && spanA[1] > acceptableWidth) { MakePolysOfProportion(polyAfterSplit[0], polyOrganizedList, polycoverList, acceptableWidth, targetArea); } else { polyOrganizedList.Add(polyAfterSplit[0]); double areaPoly = PolygonUtility.AreaPolygon(polyAfterSplit[0]); } //end of 1st if if (spanB[0] > acceptableWidth && spanB[1] > acceptableWidth) { MakePolysOfProportion(polyAfterSplit[1], polyOrganizedList, polycoverList, acceptableWidth, targetArea); } else { polyOrganizedList.Add(polyAfterSplit[1]); } //end of 2nd if } else { polyOrganizedList.Add(polyAfterSplit[0]); polyOrganizedList.Add(polyAfterSplit[1]); } } } // end of if loop , checkingpolylists } } // end of function
public static Dictionary <string, object> FindProgCirculationNetwork(List <DeptData> deptData, Polygon2d buildingOutline, List <Polygon2d> leftOverPoly = null) { if (!ValidateObject.CheckPoly(buildingOutline)) { return(null); } if (deptData == null) { return(null); } List <Polygon2d> polygonsAllProgList = new List <Polygon2d>(); List <DeptData> deptDataAllDeptList = new List <DeptData>(); List <List <Line2d> > lineCollection = new List <List <Line2d> >(); for (int i = 0; i < deptData.Count; i++) { if ((deptData[i].DepartmentType.IndexOf(BuildLayout.KPU.ToLower()) != -1 || deptData[i].DepartmentType.IndexOf(BuildLayout.KPU.ToUpper()) != -1)) { continue; // dont add for KPU } if (deptData[i].PolyAssignedToDept == null) { continue; } polygonsAllProgList.AddRange(deptData[i].PolyAssignedToDept); } if (leftOverPoly != null) { polygonsAllProgList.AddRange(leftOverPoly); } for (int i = 0; i < polygonsAllProgList.Count; i++) { polygonsAllProgList[i] = new Polygon2d(polygonsAllProgList[i].Points); } List <Line2d> networkLine = new List <Line2d>(); for (int i = 0; i < polygonsAllProgList.Count; i++) { Polygon2d poly1 = polygonsAllProgList[i]; for (int j = i + 1; j < polygonsAllProgList.Count; j++) { Polygon2d poly2 = polygonsAllProgList[j]; Dictionary <string, object> checkNeighbor = PolygonUtility.FindPolyAdjacentEdge(poly1, poly2); if (checkNeighbor != null) { if ((bool)checkNeighbor["Neighbour"] == true) { networkLine.Add((Line2d)checkNeighbor["SharedEdge"]); } } } } List <Line2d> cleanNetworkLines = LineUtility.RemoveDuplicateLines(networkLine); cleanNetworkLines = GraphicsUtility.RemoveDuplicateslinesWithPoly(buildingOutline, cleanNetworkLines); List <List <string> > deptNeighborNames = new List <List <string> >(); List <Line2d> onlyOrthoLineList = new List <Line2d>(); for (int i = 0; i < cleanNetworkLines.Count; i++) { bool checkOrtho = ValidateObject.CheckLineOrthogonal(cleanNetworkLines[i]); if (checkOrtho == true) { onlyOrthoLineList.Add(cleanNetworkLines[i]); } } return(new Dictionary <string, object> { { "CirculationNetwork", (onlyOrthoLineList) }, { "PolygonsForAllPrograms", (polygonsAllProgList) } }); }
//make the given poly all points orthonogonal to each other internal static Polygon2d MakePolyPointsOrtho(Polygon2d poly) { Polygon2d polyReg = new Polygon2d(poly.Points); List <Point2d> ptForOrthoPoly = new List <Point2d>(); for (int i = 0; i < polyReg.Points.Count; i++) { Point2d pt = Point2d.ByCoordinates(polyReg.Points[i].X, polyReg.Points[i].Y); ptForOrthoPoly.Add(pt); } for (int i = 0; i < polyReg.Points.Count; i++) { int a = i, b = i + 1; double eps = 50; if (i == polyReg.Points.Count - 1) { b = 0; } Line2d line = new Line2d(polyReg.Points[a], polyReg.Points[b]); if (ValidateObject.CheckLineOrient(line) == -1) { //double diffX = Math.Abs(line.StartPoint.X - line.EndPoint.X); //double diffY = Math.Abs(line.StartPoint.Y - line.EndPoint.Y); Point2d cenPoly = PolygonUtility.CentroidOfPoly(polyReg); Point2d ptEndA = Point2d.ByCoordinates(polyReg.Points[a].X + eps, polyReg.Points[a].Y); Line2d refLineA = Line2d.ByStartPointEndPoint(polyReg.Points[a], ptEndA); Point2d ptEndB = Point2d.ByCoordinates(polyReg.Points[b].X + eps, polyReg.Points[b].Y); Line2d refLineB = Line2d.ByStartPointEndPoint(polyReg.Points[b], ptEndB); Point2d projectedPtA = GraphicsUtility.ProjectedPointOnLine(refLineB, polyReg.Points[a]); Point2d projectedPtB = GraphicsUtility.ProjectedPointOnLine(refLineA, polyReg.Points[b]); Vector2d vecA = new Vector2d(projectedPtA, cenPoly); Vector2d vecB = new Vector2d(projectedPtB, cenPoly); double vecALength = vecA.Length; double vecBLength = vecB.Length; if (vecALength > vecBLength) { //ptForOrthoPoly[i] = projectedPtA; ptForOrthoPoly.Insert(b, projectedPtB); } else { //ptForOrthoPoly[i] = projectedPtB; ptForOrthoPoly.Insert(b, projectedPtA); } /* * if (diffX > diffY) * { * Point2d ptEndA = Point2d.ByCoordinates(polyReg.Points[a].X, polyReg.Points[a].Y + eps); * Line2d refLineA = Line2d.ByStartPointEndPoint(polyReg.Points[a], ptEndA); * refLineA = LineUtility.extend(refLineA); * * Point2d ptEndB = Point2d.ByCoordinates(polyReg.Points[b].X, polyReg.Points[b].Y + eps); * Line2d refLineB = Line2d.ByStartPointEndPoint(polyReg.Points[b], ptEndB); * refLineB = LineUtility.extend(refLineB); * * Point2d projectedPtA = GraphicsUtility.ProjectedPointOnLine(refLineB, polyReg.Points[a]); * Point2d projectedPtB = GraphicsUtility.ProjectedPointOnLine(refLineA, polyReg.Points[b]); * * Vector2d vecA = new Vector2d(projectedPtA, cenPoly); * Vector2d vecB = new Vector2d(projectedPtB, cenPoly); * double vecALength = vecA.Length; * double vecBLength = vecB.Length; * if(vecALength < vecBLength) * { * //ptForOrthoPoly[i] = projectedPtA; * ptForOrthoPoly.Insert(b, projectedPtB); * } * else * { * //ptForOrthoPoly[i] = projectedPtB; * ptForOrthoPoly.Insert(b, projectedPtA); * } * } * else * { * * Point2d ptEndA = Point2d.ByCoordinates(polyReg.Points[a].X + eps, polyReg.Points[a].Y); * Line2d refLineA = Line2d.ByStartPointEndPoint(polyReg.Points[a], ptEndA); * refLineA = LineUtility.extend(refLineA); * * Point2d ptEndB = Point2d.ByCoordinates(polyReg.Points[b].X + eps, polyReg.Points[b].Y); * Line2d refLineB = Line2d.ByStartPointEndPoint(polyReg.Points[b], ptEndB); * refLineB = LineUtility.extend(refLineB); * * Point2d projectedPtA = GraphicsUtility.ProjectedPointOnLine(refLineB, polyReg.Points[a]); * Point2d projectedPtB = GraphicsUtility.ProjectedPointOnLine(refLineA, polyReg.Points[b]); * * Vector2d vecA = new Vector2d(projectedPtA, cenPoly); * Vector2d vecB = new Vector2d(projectedPtB, cenPoly); * double vecALength = vecA.Length; * double vecBLength = vecB.Length; * if (vecALength < vecBLength) * { * //ptForOrthoPoly[i] = projectedPtA; * ptForOrthoPoly.Insert(b, projectedPtB); * } * else * { * //ptForOrthoPoly[i] = projectedPtB; * ptForOrthoPoly.Insert(b, projectedPtB); * } * } */ } } return(new Polygon2d(ptForOrthoPoly)); }