public Population(int populationSize, Boolean initialise, Paths pgs, IntPoint m_startPoint,Tour greedtour) { this.oripaths = pgs; //保存传入的路劲集合,用来计算适应度,及距离 this.startPoint = m_startPoint; tours = new Tour[populationSize]; //种群路劲集合 int greedseedsize = 15; // If we need to initialise a population of tours do so if (initialise) { for (int j = 0; j < greedseedsize; j++) { saveTour(j, greedtour); } // Loop and create individuals for (int i = greedseedsize; i < populationSize; i++) { Tour newTour = new Tour(pgs.Count); newTour.generateIndividual(); saveTour(i, newTour); } } }
public static int GetMask(Vector2i p) { int mask = 0; if (p.x == currentLowerPoint.x) { mask = mask | 1; } if (p.x == currentUpperPoint.x) { mask = mask | 2; } if (p.y == currentLowerPoint.y) { mask = mask | 4; } if (p.y == currentUpperPoint.y) { mask = mask | 8; } return(mask); }
private static Vector2 ConvertToFloatingPoint(ClipperLib.IntPoint p, Box2 range) { return(new Vector2 ( ConvertToFloatingPoint(p.X, range.XRange), ConvertToFloatingPoint(p.Y, range.YRange) )); }
public static Vector2f ToVector2f(this Vector2i p) { return(new Vector2f { x = (float)(p.x / float2int64), y = (float)(p.y / float2int64) }); }
public static bool PointNotLieOnEdges(Vector2i p) { //return p.x != currentLowerPoint.x && p.x != currentUpperPoint.x // && p.y != currentLowerPoint.y && p.y != currentUpperPoint.y; return(p.x - currentLowerPoint.x - epsilon > 0 && p.y - currentLowerPoint.y - epsilon > 0 && currentUpperPoint.x - p.x - epsilon > 0 && currentUpperPoint.y - p.y - epsilon > 0); }
public static Vector3 ToVector3f(this Vector2i p) { return(new Vector3 { x = (float)(p.x / float2int64), y = (float)(p.y / float2int64), z = 0f }); }
public static bool pointInPolygon(SvgPoint point, NFP polygon) { // scaling is deliberately coarse to filter out points that lie *on* the polygon var p = svgToClipper2(polygon, 1000); var pt = new ClipperLib.IntPoint(1000 * point.x, 1000 * point.y); return(ClipperLib.Clipper.PointInPolygon(pt, p.ToList()) > 0); }
public PointMatrix(IntPoint p) { matrix[0] = p.X; matrix[1] = p.Y; double f = Sqrt((matrix[0] * matrix[0]) + (matrix[1] * matrix[1])); matrix[0] /= f; matrix[1] /= f; matrix[2] = -matrix[1]; matrix[3] = matrix[0]; }
public static void ApplyTranslation(this Polygons polygons, IntPoint translation) { for (int i = 0; i < polygons.Count; i++) { for (int j = 0; j < polygons[i].Count; j++) { polygons[i][j] = polygons[i][j] + translation; } } }
public Line(Vector2i p1, Vector2i p2) { Vector2i d = new Vector2i { x = p2.x - p1.x, y = p2.y - p1.y }; float m = Mathf.Sqrt(d.x * d.x + d.y * d.y); a = -d.y / m; b = d.x / m; c = -(a * p1.x + b * p1.y); angle = 0f; }
void BuildVertices(Vector2 center) { vertices.Clear(); for (int i = 0; i < segmentCount; i++) { float angle = Mathf.Deg2Rad * (-90f - 360f / segmentCount * i); Vector2 point = new Vector2(center.x + radius * Mathf.Cos(angle), center.y + radius * Mathf.Sin(angle)); Vector2i point_i64 = point.ToVector2i(); vertices.Add(point_i64); } }
public static bool GetPoint(Vector2[] quad, bool outter, out List<Vector2> list, bool isClose=true) { List<IntPoint> quadLines = new List<IntPoint>(); for(int i=0; i < quad.Length; i++){ Vector3 from = quad[i]; IntPoint to = new IntPoint(from.x * DrawHelper.ClipScalling, from.y * DrawHelper.ClipScalling); quadLines.Add(to); // IntPoint to = quad[i+1]; // to = new IntPoint(to.X * scale.X * scalling, to.Y * scale.Y * scalling); // quadLines.Add(to); } EndType endType = EndType.etOpenButt; if(isClose){ endType = EndType.etClosedPolygon; } //Debug.Log("endType: " + endType); ClipperOffset co = new ClipperOffset(); co.AddPath(quadLines, JoinType.jtMiter, endType); Paths solution = new Paths(); double delta = -DrawHelper.WallThick/2 * DrawHelper.ClipScalling; if(outter){ delta = -delta; } co.MiterLimit = 8; co.Execute(ref solution, delta); list = new List<Vector2>(); if(solution.Count > 0){ foreach(IntPoint p in solution[0]){ Vector3 re = new Vector3(p.X * 1.0f/DrawHelper.ClipScalling, p.Y * 1.0f/DrawHelper.ClipScalling, 0f); if(!isClose){ //Debug.Log("result: " + re); } list.Add(re); } list.Add(list[0]); return Clipper.Orientation(solution[0]); } else{ Debug.LogError("no solution.."); } return true; }
public static bool IsVertexConcave(this Polygon vertices, int vertex) { IntPoint current = vertices[vertex]; IntPoint next = vertices[(vertex + 1) % vertices.Count]; IntPoint previous = vertices[vertex == 0 ? vertices.Count - 1 : vertex - 1]; IntPoint left = new IntPoint(current.X - previous.X, current.Y - previous.Y); IntPoint right = new IntPoint(next.X - current.X, next.Y - current.Y); long cross = (left.X * right.Y) - (left.Y * right.X); return cross < 0; }
public void InsideOutsidePoints() { { // a square with a hole (outside is ccw inside is cw) // __________ // | _____ | // | | | | // | |____| | // |________| string partOutlineString = "x:0, y:0,x:1000, y:0,x:1000, y:1000,x:0, y:1000,|x:100, y:100,x:0, y:900,x:900, y:900,x:900, y:0,|"; Polygons bounderyPolygons = PolygonsHelper.CreateFromString(partOutlineString); AvoidCrossingPerimeters testHarness = new AvoidCrossingPerimeters(bounderyPolygons); Assert.IsTrue(testHarness.PointIsInsideBoundary(new IntPoint(1, 1))); } // Here is a test case that was failing. { // Looks a little like this // _____ // | | // | O | // | O | // |___| string partOutlineString = "x:90501, y:80501,x:109500, y:80501,x:109500, y:119500,x:90501, y:119500,|x:97387, y:104041,x:95594, y:105213,x:94278, y:106903,x:93583, y:108929,x:93583, y:111071,x:94278, y:113097,x:95594, y:114787,x:97387, y:115959,x:99464, y:116485,x:101598, y:116307,x:103559, y:115447,x:105135, y:113996,x:106154, y:112113,x:106507, y:110000,x:106154, y:107887,x:105135, y:106004,x:103559, y:104553,x:101598, y:103693,x:99464, y:103515,|x:97387, y:84042,x:95594, y:85214,x:94278, y:86904,x:93583, y:88930,x:93583, y:91072,x:94278, y:93098,x:95594, y:94788,x:97387, y:95960,x:99464, y:96486,x:101598, y:96308,x:103559, y:95448,x:105135, y:93997,x:106154, y:92114,x:106507, y:90001,x:106154, y:87888,x:105135, y:86005,x:103559, y:84554,x:101598, y:83694,x:99464, y:83516,|"; Polygons bounderyPolygons = PolygonsHelper.CreateFromString(partOutlineString); IntPoint startPoint = new IntPoint(95765, 114600); IntPoint endPoint = new IntPoint(99485, 96234); AvoidCrossingPerimeters testHarness = new AvoidCrossingPerimeters(bounderyPolygons); { IntPoint startPointInside = startPoint; testHarness.MovePointInsideBoundary(ref startPointInside); IntPoint endPointInside = endPoint; testHarness.MovePointInsideBoundary(ref endPointInside); Assert.IsTrue(testHarness.PointIsInsideBoundary(startPointInside)); Assert.IsTrue(testHarness.PointIsInsideBoundary(endPointInside)); Polygon insidePath = new Polygon(); testHarness.CreatePathInsideBoundary(startPointInside, endPointInside, insidePath); Assert.IsTrue(insidePath.Count > 10); // It needs to go around the cicle so it needs many points (2 is a definate fail). } { Polygon insidePath = new Polygon(); testHarness.CreatePathInsideBoundary(startPoint, endPoint, insidePath); Assert.IsTrue(insidePath.Count > 12); // two more than the last test to get the points in the right place } } }
public List <Vector2i> GetVertices() { List <Vector2i> vertices = new List <Vector2i>(); for (int i = 0; i < segmentCount; i++) { float angle = Mathf.Deg2Rad * (-90f - 360f / segmentCount * i); Vector2 point = new Vector2(clipPosition.x + radius * Mathf.Cos(angle), clipPosition.y + radius * Mathf.Sin(angle)); Vector2i point_i64 = point.ToVector2i(); vertices.Add(point_i64); } return(vertices); }
public void Clip(TurningChisel chisel) { if (polygon == null) { return; } List <Polygon> solution = new List <Polygon>(); ClipperLib.Clipper clipper = new ClipperLib.Clipper(); clipper.AddPolygon(polygon, ClipperLib.PolyType.ptSubject); clipper.AddPolygon(chisel.Polygon, ClipperLib.PolyType.ptClip); clipper.Execute(ClipperLib.ClipType.ctDifference, solution, ClipperLib.PolyFillType.pftNonZero, ClipperLib.PolyFillType.pftNonZero); polygon = null; if (solution.Count > 0) { Vector2i basePosition = transform.localPosition.ToVector2i(); polygon = null; for (int i = 0; i < solution.Count; i++) { var poly = solution[i]; float xA = (float)(poly[1].X - basePosition.X); float xB = (float)(poly[poly.Count - 2].X - basePosition.Y); if (xA * xB < 0f) { polygon = poly; } else { StartCoroutine(CreateDetachedObject(poly)); } } } if (polygon != null) { ExtractEdge(); PostShapeChange(); } else { polygon = null; ExtractEdge(); PostShapeChange(); } }
public static bool Inside(IList<IntPoint> polygon, IntPoint position, bool toleranceOnOutside = true) { IntPoint point = position; const float epsilon = 0.5f; bool inside = false; // Must have 3 or more edges if (polygon.Count < 3) return false; IntPoint oldPoint = polygon[polygon.Count - 1]; float oldSqDist = (oldPoint - point).LengthSquared(); for (int i = 0; i < polygon.Count; i++) { IntPoint newPoint = polygon[i]; float newSqDist = (newPoint - point).LengthSquared(); if (oldSqDist + newSqDist + 2.0f * System.Math.Sqrt(oldSqDist * newSqDist) - (newPoint - oldPoint).LengthSquared() < epsilon) { return toleranceOnOutside; } IntPoint left; IntPoint right; if (newPoint.X > oldPoint.X) { left = oldPoint; right = newPoint; } else { left = newPoint; right = oldPoint; } if (left.X < point.X && point.X <= right.X && (point.Y - left.Y) * (right.X - left.X) < (right.Y - left.Y) * (point.X - left.X)) { inside = !inside; } oldPoint = newPoint; oldSqDist = newSqDist; } return inside; }
public GCodePlanner(GCodeExport gcode, int travelSpeed, int retractionMinimumDistance_um) { this.gcodeExport = gcode; travelConfig = new GCodePathConfig(travelSpeed, 0, "travel"); LastPosition = gcode.GetPositionXY(); outerPerimetersToAvoidCrossing = null; extrudeSpeedFactor = 100; travelSpeedFactor = 100; extraTime = 0.0; totalPrintTime = 0.0; forceRetraction = false; alwaysRetract = false; currentExtruderIndex = gcode.GetExtruderIndex(); this.retractionMinimumDistance_um = retractionMinimumDistance_um; }
public static List<Vector2> Add(this Shape shape, Shape secondShape, Action<Shape> completed) { List<Vector2> points = new List<Vector2>(); Clipper c = new Clipper(); List<List<IntPoint>> subj = new List<List<IntPoint>>(); List<List<IntPoint>> clip = new List<List<IntPoint>>(); List<List<IntPoint>> solution = new List<List<IntPoint>>(); List<IntPoint> p1 = new List<IntPoint>(); List<IntPoint> p2 = new List<IntPoint>(); int i = 0, l = shape.Points.Length; Vector2 pos = shape.BuiltGameObject.transform.position; for(;i<l;++i) { IntPoint ip = new IntPoint(shape.Points[i].x + pos.x,shape.Points[i].y + pos.y); p1.Add(ip); } p1.Add(p1[0]); pos = secondShape.BuiltGameObject.transform.position; i = 0; l = secondShape.Points.Length; for(;i<l;++i) { IntPoint ip = new IntPoint(secondShape.Points[i].x + pos.x,secondShape.Points[i].y + pos.y); p2.Add(ip); } p2.Add(p2[0]); subj.Add(p1); clip.Add(p2); c.AddPaths(subj,PolyType.ptSubject,true); c.AddPaths(clip,PolyType.ptClip,true); c.Execute(ClipType.ctUnion,solution); i = 0; l = solution[0].Count; for(;i<l;++i) { float x = System.Convert.ToSingle(solution[0][i].X); float y = System.Convert.ToSingle(solution[0][i].Y); points.Add(new Vector2(x,y)); } Mesh2D.Instance.ReBuild(shape.BuiltGameObject,points,completed,shape.Col); return points; }
//------------------------------------------------------------------------------ public void AddPath(List<IntPoint> path, JoinType joinType, EndType endType) { int highI = path.Count - 1; if (highI < 0) return; PolyNode newNode = new PolyNode(); newNode.m_jointype = joinType; newNode.m_endtype = endType; //strip duplicate points from path and also get index to the lowest point ... if (endType == EndType.etClosedLine || endType == EndType.etClosedPolygon) while (highI > 0 && path[0] == path[highI]) highI--; newNode.m_polygon.Capacity = highI + 1; newNode.m_polygon.Add(path[0]); int j = 0, k = 0; for (int i = 1; i <= highI; i++) if (newNode.m_polygon[j] != path[i]) { j++; newNode.m_polygon.Add(path[i]); if (path[i].Y > newNode.m_polygon[k].Y || (path[i].Y == newNode.m_polygon[k].Y && path[i].X < newNode.m_polygon[k].X)) k = j; } if (endType == EndType.etClosedPolygon && j < 2) return; m_polyNodes.AddChild(newNode); //if this path's lowest pt is lower than all the others then update m_lowest if (endType != EndType.etClosedPolygon) return; if (m_lowest.X < 0) m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, k); else { IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X].m_polygon[(int)m_lowest.Y]; if (newNode.m_polygon[k].Y > ip.Y || (newNode.m_polygon[k].Y == ip.Y && newNode.m_polygon[k].X < ip.X)) m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, k); } }
void BuildVertices(Vector2 begin, Vector2 end) { vertices.Clear(); int halfSegmentCount = segmentCount / 2; touchLine = new TouchLineOverlapCheck(begin, end); for (int i = 0; i <= halfSegmentCount; i++) { float angle = Mathf.Deg2Rad * (touchLine.angle + 270f - (float)360f / segmentCount * i); Vector2 point = new Vector2(begin.x + radius * Mathf.Cos(angle), begin.y + radius * Mathf.Sin(angle)); Vector2i point_i64 = point.ToVector2i(); vertices.Add(point_i64); } for (int i = halfSegmentCount; i <= segmentCount; i++) { float angle = Mathf.Deg2Rad * (touchLine.angle + 270f - (float)360f / segmentCount * i); Vector2 point = new Vector2(end.x + radius * Mathf.Cos(angle), end.y + radius * Mathf.Sin(angle)); Vector2i point_i64 = point.ToVector2i(); vertices.Add(point_i64); } }
public bool IsOutside(Vector2 point) { var p = new IntPoint(point.X, point.Y); return Clipper.PointInPolygon(p, ToClipperPath()) != 1; }
public static bool PointInPolygon(Polygon polygon, IntPoint testPosition) { int numPoints = polygon.Count; bool result = false; for (int i = 0; i < numPoints; i++) { int prevIndex = i - 1; if (prevIndex < 0) { prevIndex += numPoints; } if ((((polygon[i].Y <= testPosition.Y) && (testPosition.Y < polygon[prevIndex].Y)) || ((polygon[prevIndex].Y <= testPosition.Y) && (testPosition.Y < polygon[i].Y))) && (testPosition.X - polygon[i].X < (polygon[prevIndex].X - polygon[i].X) * (testPosition.Y - polygon[i].Y) / (polygon[prevIndex].Y - polygon[i].Y))) { result = !result; } } return result; }
//------------------------------------------------------------------------------ private void BuildIntersectList(Int64 botY, Int64 topY) { if ( m_ActiveEdges == null ) return; //prepare for sorting ... TEdge e = m_ActiveEdges; e.tmpX = TopX( e, topY ); m_SortedEdges = e; m_SortedEdges.prevInSEL = null; e = e.nextInAEL; while( e != null ) { e.prevInSEL = e.prevInAEL; e.prevInSEL.nextInSEL = e; e.nextInSEL = null; e.tmpX = TopX( e, topY ); e = e.nextInAEL; } //bubblesort ... bool isModified = true; while( isModified && m_SortedEdges != null ) { isModified = false; e = m_SortedEdges; while( e.nextInSEL != null ) { TEdge eNext = e.nextInSEL; IntPoint pt = new IntPoint(); if(e.tmpX > eNext.tmpX && IntersectPoint(e, eNext, ref pt)) { if (pt.Y > botY) { pt.Y = botY; pt.X = TopX(e, pt.Y); } AddIntersectNode(e, eNext, pt); SwapPositionsInSEL(e, eNext); isModified = true; } else e = eNext; } if( e.prevInSEL != null ) e.prevInSEL.nextInSEL = null; else break; } m_SortedEdges = null; }
//------------------------------------------------------------------------------ private void AddLocalMinPoly(TEdge e1, TEdge e2, IntPoint pt) { if (e2.dx == horizontal || (e1.dx > e2.dx)) { AddOutPt(e1, e2, pt); e2.outIdx = e1.outIdx; e1.side = EdgeSide.esLeft; e2.side = EdgeSide.esRight; } else { AddOutPt(e2, e1, pt); e1.outIdx = e2.outIdx; e1.side = EdgeSide.esRight; e2.side = EdgeSide.esLeft; } }
//------------------------------------------------------------------------------ private void AddIntersectNode(TEdge e1, TEdge e2, IntPoint pt) { IntersectNode newNode = new IntersectNode(); newNode.edge1 = e1; newNode.edge2 = e2; newNode.pt = pt; newNode.next = null; if (m_IntersectNodes == null) m_IntersectNodes = newNode; else if( Process1Before2(newNode, m_IntersectNodes) ) { newNode.next = m_IntersectNodes; m_IntersectNodes = newNode; } else { IntersectNode iNode = m_IntersectNodes; while( iNode.next != null && Process1Before2(iNode.next, newNode) ) iNode = iNode.next; newNode.next = iNode.next; iNode.next = newNode; } }
//------------------------------------------------------------------------------ internal bool Pt3IsBetweenPt1AndPt2(IntPoint pt1, IntPoint pt2, IntPoint pt3) { if (PointsEqual(pt1, pt3) || PointsEqual(pt2, pt3)) return true; else if (pt1.X != pt2.X) return (pt1.X < pt3.X) == (pt3.X < pt2.X); else return (pt1.Y < pt3.Y) == (pt3.Y < pt2.Y); }
//------------------------------------------------------------------------------ // OffsetPolygon functions ... //------------------------------------------------------------------------------ internal static Polygon BuildArc(IntPoint pt, double a1, double a2, double r) { int steps = Math.Max(6, (int)(Math.Sqrt(Math.Abs(r)) * Math.Abs(a2 - a1))); Polygon result = new Polygon(steps); int n = steps - 1; double da = (a2 - a1) / n; double a = a1; for (int i = 0; i < steps; ++i) { result.Add(new IntPoint(pt.X + Round(Math.Cos(a) * r), pt.Y + Round(Math.Sin(a) * r))); a += da; } return result; }
public static PolyTree ExecuteClipper(TmxMap map, TmxChunk chunk, TransformPointFunc xfFunc) { ////for(int i=0;i<chunk.Height;i++) //// { //// for(int j=0; j<chunk.Width;j++) //// { //// var raw = chunk.GetRawTileIdAt(j, i); //// if(raw!=0) //// { //// var tid = TmxMath.GetTileIdWithoutFlags(raw); //// var tile = map.Tiles[tid]; //// foreach(var p in tile.ObjectGroup.Objects) //// { //// if(p is TmxHasPoints) //// { //// p.ToEnumerable().Where((x) => //// { //// if (!usingUnityLayerOverride) //// { //// return string.Compare(tuple.Item1.Type, chunk.ParentData.ParentLayer.Name, true) == 0; //// } //// return true; //// }); //// } //// } //// } //// } //// } // Clipper clipper = new Clipper(0); // Tuple<TmxObject, TmxTile, uint> tuple = new Tuple<TmxObject, TmxTile, uint>(null, null, 0); // bool usingUnityLayerOverride = !string.IsNullOrEmpty(chunk.ParentData.ParentLayer.UnityLayerOverrideName); // foreach (var item2 in from h__TransparentIdentifier4 in (from y in Enumerable.Range(0, chunk.Height) // from x in Enumerable.Range(0, chunk.Width) // let rawTileId = chunk.GetRawTileIdAt(x, y) // where rawTileId != 0 // let tileId = TmxMath.GetTileIdWithoutFlags(rawTileId) // let tile = map.Tiles[tileId] // from polygon in tile.ObjectGroup.Objects // where polygon is TmxHasPoints // select polygon.ToEnumerable().ToList().TrueForAll // (h__TransparentIdentifier4 => // { // UnityEngine.Debug.Log("liudaodelh"); // tuple = new Tuple<TmxObject, TmxTile, uint>(polygon, tile, rawTileId); // if (!usingUnityLayerOverride) // { // return string.Compare(tuple.Item1.Type, chunk.ParentData.ParentLayer.Name, true) == 0; // } // return true; // })) // select new // { // PositionOnMap = map.GetMapPositionAt((int)tuple.Item1.Position.X + chunk.X, (int)tuple.Item1.Position.Y + chunk.Y, tuple.Item2), // HasPointsInterface = (tuple.Item1 as TmxHasPoints), // TmxObjectInterface = tuple.Item1, // IsFlippedDiagnoally = TmxMath.IsTileFlippedDiagonally(tuple.Item3), // IsFlippedHorizontally = TmxMath.IsTileFlippedHorizontally(tuple.Item3), // IsFlippedVertically = TmxMath.IsTileFlippedVertically(tuple.Item3), // TileCenter = new PointF((float)tuple.Item2.TileSize.Width * 0.5f, (float)tuple.Item2.TileSize.Height * 0.5f) // }) // { // List<IntPoint> list = new List<IntPoint>(); // SizeF offset = new SizeF(item2.TmxObjectInterface.Position); // PointF[] array = item2.HasPointsInterface.Points.Select((PointF pt) => PointF.Add(pt, offset)).ToArray(); // TmxMath.TransformPoints(array, item2.TileCenter, item2.IsFlippedDiagnoally, item2.IsFlippedHorizontally, item2.IsFlippedVertically); // PointF[] array2 = array; // for (int i = 0; i < array2.Length; i++) // { // PointF pointF = array2[i]; // float x2 = (float)item2.PositionOnMap.X + pointF.X; // float y2 = (float)item2.PositionOnMap.Y + pointF.Y; // IntPoint item = xfFunc(x2, y2); // list.Add(item); // } // list.Reverse(); // clipper.AddPath(list, PolyType.ptSubject, item2.HasPointsInterface.ArePointsClosed()); // } // PolyTree polyTree = new PolyTree(); // clipper.Execute(ClipType.ctUnion, polyTree, SubjectFillRule, ClipFillRule); // return polyTree; ClipperLib.Clipper clipper = new ClipperLib.Clipper(); // Limit to polygon "type" that matches the collision layer name (unless we are overriding the whole layer to a specific Unity Layer Name) bool usingUnityLayerOverride = !String.IsNullOrEmpty(chunk.ParentData.ParentLayer.UnityLayerOverrideName); var polygons = from y in Enumerable.Range(0, chunk.Height) from x in Enumerable.Range(0, chunk.Width) let rawTileId = chunk.GetRawTileIdAt(x, y) where rawTileId != 0 let tileId = TmxMath.GetTileIdWithoutFlags(rawTileId) let tile = map.Tiles[tileId] from polygon in tile.ObjectGroup.Objects where (polygon as TmxHasPoints) != null where usingUnityLayerOverride || String.Compare(polygon.Type, chunk.ParentData.ParentLayer.Name, true) == 0 select new { PositionOnMap = map.GetMapPositionAt(x + chunk.X, y + chunk.Y, tile), HasPointsInterface = polygon as TmxHasPoints, TmxObjectInterface = polygon, IsFlippedDiagnoally = TmxMath.IsTileFlippedDiagonally(rawTileId), IsFlippedHorizontally = TmxMath.IsTileFlippedHorizontally(rawTileId), IsFlippedVertically = TmxMath.IsTileFlippedVertically(rawTileId), TileCenter = new PointF(tile.TileSize.Width * 0.5f, tile.TileSize.Height * 0.5f), }; // Add all our polygons to the Clipper library so it can reduce all the polygons to a (hopefully small) number of paths foreach (var poly in polygons) { // Create a clipper library polygon out of each and add it to our collection ClipperPolygon clipperPolygon = new ClipperPolygon(); // Our points may be transformed due to tile flipping/rotation // Before we transform them we put all the points into local space relative to the tile SizeF offset = new SizeF(poly.TmxObjectInterface.Position); PointF[] transformedPoints = poly.HasPointsInterface.Points.Select(pt => PointF.Add(pt, offset)).ToArray(); // Now transform the points relative to the tile TmxMath.TransformPoints(transformedPoints, poly.TileCenter, poly.IsFlippedDiagnoally, poly.IsFlippedHorizontally, poly.IsFlippedVertically); foreach (var pt in transformedPoints) { float x = poly.PositionOnMap.X + pt.X; float y = poly.PositionOnMap.Y + pt.Y; ClipperLib.IntPoint point = xfFunc(x, y); clipperPolygon.Add(point); } // Because of Unity's cooridnate system, the winding order of the polygons must be reversed clipperPolygon.Reverse(); // Add the "subject" clipper.AddPath(clipperPolygon, ClipperLib.PolyType.ptSubject, poly.HasPointsInterface.ArePointsClosed()); } ClipperLib.PolyTree solution = new ClipperLib.PolyTree(); clipper.Execute(ClipperLib.ClipType.ctUnion, solution, LayerClipper.SubjectFillRule, LayerClipper.ClipFillRule); return(solution); }
public static Poly2Tri.PolygonPoint PP(ClipperLib.IntPoint v) { return(new Poly2Tri.PolygonPoint(v.X / 16384.0, v.Y / 16384.0)); }
public static Vector2 V2(ClipperLib.IntPoint v) { return(new Vector2((float)(v.X / 16384.0), (float)(v.Y / 16384.0))); }
public static Vector2i[] Execute(List <Vector2i> inPolygon, List <List <Vector2f> > outEdges) { int inVertexCount = inPolygon.Count; if (inVertexCount < 2) { return(null); } int[] polygonMask = new int[inVertexCount]; int removeCount = 0; if (epsilon > 0f) { RamerDouglasPeucker(inPolygon, polygonMask, 0, inVertexCount - 1, ref removeCount); } Vector2i[] outPolygon = new Vector2i[inVertexCount - removeCount]; List <Vector2f> outEdge = new List <Vector2f>(); int[] edgeMask = new int[outPolygon.Length]; int j = 0; for (int i = 0; i < inVertexCount; i++) { if (polygonMask[i] != 1) { outPolygon[j] = inPolygon[i]; edgeMask[j] = GetMask(inPolygon[i]); j++; } } int maskPrev, mask, a; for (int i = 0; i < edgeMask.Length; i++) { maskPrev = edgeMask[(i - 1 + edgeMask.Length) % edgeMask.Length]; mask = edgeMask[i]; a = mask & maskPrev; if (mask != 0 && a != 0) { if (outEdge.Count > 1) { outEdges.Add(outEdge); outEdge = new List <Vector2f>(); } else { outEdge.Clear(); } outEdge.Add(outPolygon[i].ToVector2f()); } else { outEdge.Add(outPolygon[i].ToVector2f()); } } maskPrev = edgeMask[edgeMask.Length - 1]; mask = edgeMask[0]; a = mask & maskPrev; if (mask != 0 && a != 0) { if (outEdge.Count > 1) { outEdges.Add(outEdge); outEdge = new List <Vector2f>(); } else { outEdge.Clear(); } outEdge.Add(outPolygon[0].ToVector2f()); } else { outEdge.Add(outPolygon[0].ToVector2f()); } if (outEdge.Count > 1) { outEdges.Add(outEdge); } return(outPolygon); }
public static Vector2 GetPoint(ClipperLib.IntPoint pt) { return(new Vector2((float)pt.X / clipperScale, (float)pt.Y / clipperScale)); }
public float GetDistance(Vector2i p) { return(Mathf.Abs(a * p.x + b * p.y + c)); }
public IntPoint(IntPoint pt) { this.X = pt.X; this.Y = pt.Y; }
public static PolyTree ExecuteClipper(TmxMap tmxMap, TmxLayer tmxLayer, TransformPointFunc xfFunc, ProgressFunc progFunc) { // The "fullClipper" combines the clipper results from the smaller pieces ClipperLib.Clipper fullClipper = new ClipperLib.Clipper(); // From the perspective of Clipper lines are polygons too // Closed paths == polygons // Open paths == lines var polygonGroups = from y in Enumerable.Range(0, tmxLayer.Height) from x in Enumerable.Range(0, tmxLayer.Width) let rawTileId = tmxLayer.GetRawTileIdAt(x, y) let tileId = TmxMath.GetTileIdWithoutFlags(rawTileId) where tileId != 0 let tile = tmxMap.Tiles[tileId] from polygon in tile.ObjectGroup.Objects where (polygon as TmxHasPoints) != null let groupX = x / LayerClipper.GroupBySize let groupY = y / LayerClipper.GroupBySize group new { PositionOnMap = tmxMap.GetMapPositionAt(x, y, tile), HasPointsInterface = polygon as TmxHasPoints, TmxObjectInterface = polygon, IsFlippedDiagnoally = TmxMath.IsTileFlippedDiagonally(rawTileId), IsFlippedHorizontally = TmxMath.IsTileFlippedHorizontally(rawTileId), IsFlippedVertically = TmxMath.IsTileFlippedVertically(rawTileId), TileCenter = new PointF(tile.TileSize.Width * 0.5f, tile.TileSize.Height * 0.5f), } by Tuple.Create(groupX, groupY); int groupIndex = 0; int groupCount = polygonGroups.Count(); foreach (var polyGroup in polygonGroups) { if (groupIndex % 5 == 0) { progFunc(String.Format("Clipping '{0}' polygons: {1}%", tmxLayer.UniqueName, (groupIndex / (float)groupCount) * 100)); } groupIndex++; // The "groupClipper" clips the polygons in a smaller part of the world ClipperLib.Clipper groupClipper = new ClipperLib.Clipper(); // Add all our polygons to the Clipper library so it can reduce all the polygons to a (hopefully small) number of paths foreach (var poly in polyGroup) { // Create a clipper library polygon out of each and add it to our collection ClipperPolygon clipperPolygon = new ClipperPolygon(); // Our points may be transformed due to tile flipping/rotation // Before we transform then we put all the points into local space relative to the tile SizeF offset = new SizeF(poly.TmxObjectInterface.Position); PointF[] transformedPoints = poly.HasPointsInterface.Points.Select(pt => PointF.Add(pt, offset)).ToArray(); // Now transform the points relative to the tile TmxMath.TransformPoints(transformedPoints, poly.TileCenter, poly.IsFlippedDiagnoally, poly.IsFlippedHorizontally, poly.IsFlippedVertically); foreach (var pt in transformedPoints) { float x = poly.PositionOnMap.X + pt.X; float y = poly.PositionOnMap.Y + pt.Y; ClipperLib.IntPoint point = xfFunc(x, y); clipperPolygon.Add(point); } // Because of Unity's cooridnate system, the winding order of the polygons must be reversed clipperPolygon.Reverse(); // Add the "subject" groupClipper.AddPath(clipperPolygon, ClipperLib.PolyType.ptSubject, poly.HasPointsInterface.ArePointsClosed()); } // Get a solution for this group ClipperLib.PolyTree solution = new ClipperLib.PolyTree(); groupClipper.Execute(ClipperLib.ClipType.ctUnion, solution); // Combine the solutions into the full clipper fullClipper.AddPaths(Clipper.ClosedPathsFromPolyTree(solution), PolyType.ptSubject, true); fullClipper.AddPaths(Clipper.OpenPathsFromPolyTree(solution), PolyType.ptSubject, false); } progFunc(String.Format("Clipping '{0}' polygons: 100%", tmxLayer.UniqueName)); ClipperLib.PolyTree fullSolution = new ClipperLib.PolyTree(); fullClipper.Execute(ClipperLib.ClipType.ctUnion, fullSolution); return(fullSolution); }
//------------------------------------------------------------------------------ internal static DoublePoint GetUnitNormal(IntPoint pt1, IntPoint pt2) { double dx = (pt2.X - pt1.X); double dy = (pt2.Y - pt1.Y); if ((dx == 0) && (dy == 0)) return new DoublePoint(); double f = 1 * 1.0 / Math.Sqrt(dx * dx + dy * dy); dx *= f; dy *= f; return new DoublePoint(dy, -dx); }
public static Vector3 ToVector3(this Vector2i p) { return(new Vector3(p.X / CliperLibRatio, p.Y / CliperLibRatio, 0f)); }
//------------------------------------------------------------------------------ internal void SwapPoints(ref IntPoint pt1, ref IntPoint pt2) { IntPoint tmp = pt1; pt1 = pt2; pt2 = tmp; }
public static Vector2 ToVector2(this Vector2i p) { return(new Vector2(p.X / CliperLibRatio, p.Y / CliperLibRatio)); }
//------------------------------------------------------------------------------ private void AddLocalMaxPoly(TEdge e1, TEdge e2, IntPoint pt) { AddOutPt(e1, null, pt); if (e1.outIdx == e2.outIdx) { e1.outIdx = -1; e2.outIdx = -1; } else AppendPolygon(e1, e2); }
//------------------------------------------------------------------------------ internal bool PointInPolygon(IntPoint pt, OutPt pp, bool UseFulllongRange) { OutPt pp2 = pp; bool result = false; if (UseFulllongRange) { do { if ((((pp2.pt.Y <= pt.Y) && (pt.Y < pp2.prev.pt.Y)) || ((pp2.prev.pt.Y <= pt.Y) && (pt.Y < pp2.pt.Y))) && new Int128(pt.X - pp2.pt.X) < Int128.Int128Mul(pp2.prev.pt.X - pp2.pt.X, pt.Y - pp2.pt.Y) / new Int128(pp2.prev.pt.Y - pp2.pt.Y)) result = !result; pp2 = pp2.next; } while (pp2 != pp); } else { do { if ((((pp2.pt.Y <= pt.Y) && (pt.Y < pp2.prev.pt.Y)) || ((pp2.prev.pt.Y <= pt.Y) && (pt.Y < pp2.pt.Y))) && (pt.X - pp2.pt.X < (pp2.prev.pt.X - pp2.pt.X) * (pt.Y - pp2.pt.Y) / (pp2.prev.pt.Y - pp2.pt.Y))) result = !result; pp2 = pp2.next; } while (pp2 != pp); } return result; }
//------------------------------------------------------------------------------ private void AddOutPt(TEdge e, TEdge altE, IntPoint pt) { bool ToFront = (e.side == EdgeSide.esLeft); if( e.outIdx < 0 ) { OutRec outRec = CreateOutRec(); m_PolyOuts.Add(outRec); outRec.idx = m_PolyOuts.Count -1; e.outIdx = outRec.idx; OutPt op = new OutPt(); outRec.pts = op; outRec.bottomPt = op; outRec.bottomE1 = e; outRec.bottomE2 = altE; op.pt = pt; op.idx = outRec.idx; op.next = op; op.prev = op; SetHoleState(e, outRec); } else { OutRec outRec = m_PolyOuts[e.outIdx]; OutPt op = outRec.pts; if (ToFront && PointsEqual(pt, op.pt) || (!ToFront && PointsEqual(pt, op.prev.pt))) return; OutPt op2 = new OutPt(); op2.pt = pt; op2.idx = outRec.idx; if (op2.pt.Y == outRec.bottomPt.pt.Y && op2.pt.X < outRec.bottomPt.pt.X) { outRec.bottomPt = op2; outRec.bottomE1 = e; outRec.bottomE2 = altE; } op2.next = op; op2.prev = op.prev; op2.prev.next = op2; op.prev = op2; if (ToFront) outRec.pts = op2; } }
//------------------------------------------------------------------------------ internal bool PointIsVertex(IntPoint pt, OutPt pp) { OutPt pp2 = pp; do { if (PointsEqual(pp2.pt, pt)) return true; pp2 = pp2.next; } while (pp2 != pp); return false; }
//--------------------------------------------------------------------- private IntPoint GenerateRandomPoint(int l, int t, int r, int b, Random rand) { int Q = 10; IntPoint newPt = new IntPoint(); newPt.X = (rand.Next(r / Q) * Q + l + 10) * scale; newPt.Y = (rand.Next(b / Q) * Q + t + 10) * scale; return newPt; }
//------------------------------------------------------------------------------ protected static bool PointsEqual(IntPoint pt1, IntPoint pt2) { return ( pt1.X == pt2.X && pt1.Y == pt2.Y ); }
static public PolyTree FindDistictObjectBounds(ImageBuffer image) { MarchingSquaresByte marchingSquaresData = new MarchingSquaresByte(image, 5, 0); marchingSquaresData.CreateLineSegments(); Polygons lineLoops = marchingSquaresData.CreateLineLoops(1); if (lineLoops.Count == 1) { return null; } // create a bounding polygon to clip against IntPoint min = new IntPoint(long.MaxValue, long.MaxValue); IntPoint max = new IntPoint(long.MinValue, long.MinValue); foreach (Polygon polygon in lineLoops) { foreach (IntPoint point in polygon) { min.X = Math.Min(point.X - 10, min.X); min.Y = Math.Min(point.Y - 10, min.Y); max.X = Math.Max(point.X + 10, max.X); max.Y = Math.Max(point.Y + 10, max.Y); } } Polygon boundingPoly = new Polygon(); boundingPoly.Add(min); boundingPoly.Add(new IntPoint(min.X, max.Y)); boundingPoly.Add(max); boundingPoly.Add(new IntPoint(max.X, min.Y)); // now clip the polygons to get the inside and outside polys Clipper clipper = new Clipper(); clipper.AddPaths(lineLoops, PolyType.ptSubject, true); clipper.AddPath(boundingPoly, PolyType.ptClip, true); PolyTree polyTreeForPlate = new PolyTree(); clipper.Execute(ClipType.ctIntersection, polyTreeForPlate); return polyTreeForPlate; }
//------------------------------------------------------------------------------ protected bool SlopesEqual(IntPoint pt1, IntPoint pt2, IntPoint pt3, IntPoint pt4, bool UseFulllongRange) { if (pt1.Y == pt2.Y) return (pt3.Y == pt4.Y); else if (pt1.X == pt2.X) return (pt3.X == pt4.X); else if (UseFulllongRange) return Int128.Int128Mul(pt1.Y - pt2.Y, pt3.X - pt4.X) == Int128.Int128Mul(pt1.X - pt2.X, pt3.Y - pt4.Y); else return (Int64)(pt1.Y - pt2.Y) * (pt3.X - pt4.X) - (Int64)(pt1.X - pt2.X) * (pt3.Y - pt4.Y) == 0; }
/// <summary> /// Checks if the point is outside of polygon /// </summary> /// <param name="val">Polygon to check</param> /// <param name="point">Point to check</param> /// <returns>true if point is outside of polygon</returns> public static bool IsOutside(this Geometry.Polygon val, Vector2 point) { var p = new IntPoint(point.X, point.Y); return Clipper.PointInPolygon(p, val.ToClipperPath()) != 1; }
//------------------------------------------------------------------------------ private void InitEdge(TEdge e, TEdge eNext, TEdge ePrev, IntPoint pt, PolyType polyType) { e.next = eNext; e.prev = ePrev; e.xcurr = pt.X; e.ycurr = pt.Y; if (e.ycurr >= e.next.ycurr) { e.xbot = e.xcurr; e.ybot = e.ycurr; e.xtop = e.next.xcurr; e.ytop = e.next.ycurr; e.windDelta = 1; } else { e.xtop = e.xcurr; e.ytop = e.ycurr; e.xbot = e.next.xcurr; e.ybot = e.next.ycurr; e.windDelta = -1; } SetDx(e); e.polyType = polyType; e.outIdx = -1; }