/// <summary> /// Marching squares over the given domain using the mesh defined via the dimensions /// (wid,hei) to build a set of polygons such that f(x,y) less than 0, using the given number /// 'bin' for recursive linear inteprolation along cell boundaries. /// /// if 'comb' is true, then the polygons will also be composited into larger possible concave /// polygons. /// </summary> /// <param name="domain"></param> /// <param name="cellWidth"></param> /// <param name="cellHeight"></param> /// <param name="f"></param> /// <param name="lerpCount"></param> /// <param name="combine"></param> /// <returns></returns> public static List <Vertices> DetectSquares(Box2D.AABB domain, float cellWidth, float cellHeight, sbyte[,] f, int lerpCount, bool combine) { CxFastList <GeomPoly> ret = new CxFastList <GeomPoly>(); List <Vertices> verticesList = new List <Vertices>(); //NOTE: removed assignments as they were not used. List <GeomPoly> polyList; GeomPoly gp; int xn = (int)(domain.GetExtents().x * 2 / cellWidth); bool xp = xn == (domain.GetExtents().x * 2 / cellWidth); int yn = (int)(domain.GetExtents().y * 2 / cellHeight); bool yp = yn == (domain.GetExtents().y * 2 / cellHeight); if (!xp) { xn++; } if (!yp) { yn++; } sbyte[,] fs = new sbyte[xn + 1, yn + 1]; GeomPolyVal[,] ps = new GeomPolyVal[xn + 1, yn + 1]; //populate shared function lookups. for (int x = 0; x < xn + 1; x++) { int x0; if (x == xn) { x0 = (int)domain.upperBound.x; } else { x0 = (int)(x * cellWidth + domain.lowerBound.x); } for (int y = 0; y < yn + 1; y++) { int y0; if (y == yn) { y0 = (int)domain.upperBound.y; } else { y0 = (int)(y * cellHeight + domain.lowerBound.y); } fs[x, y] = f[x0, y0]; } } //generate sub-polys and combine to scan lines for (int y = 0; y < yn; y++) { float y0 = y * cellHeight + domain.lowerBound.y; float y1; if (y == yn - 1) { y1 = domain.upperBound.y; } else { y1 = y0 + cellHeight; } GeomPoly pre = null; for (int x = 0; x < xn; x++) { float x0 = x * cellWidth + domain.lowerBound.x; float x1; if (x == xn - 1) { x1 = domain.upperBound.x; } else { x1 = x0 + cellWidth; } gp = new GeomPoly(); int key = MarchSquare(f, fs, ref gp, x, y, x0, y0, x1, y1, lerpCount); if (gp.Length != 0) { if (combine && pre != null && (key & 9) != 0) { combLeft(ref pre, ref gp); gp = pre; } else { ret.Add(gp); } ps[x, y] = new GeomPolyVal(gp, key); } else { gp = null; } pre = gp; } } if (!combine) { polyList = ret.GetListOfElements(); foreach (GeomPoly poly in polyList) { verticesList.Add(new Vertices(poly.Points.GetListOfElements())); } return(verticesList); } //combine scan lines together for (int y = 1; y < yn; y++) { int x = 0; while (x < xn) { GeomPolyVal p = ps[x, y]; //skip along scan line if no polygon exists at this point if (p == null) { x++; continue; } //skip along if current polygon cannot be combined above. if ((p.Key & 12) == 0) { x++; continue; } //skip along if no polygon exists above. GeomPolyVal u = ps[x, y - 1]; if (u == null) { x++; continue; } //skip along if polygon above cannot be combined with. if ((u.Key & 3) == 0) { x++; continue; } float ax = x * cellWidth + domain.lowerBound.x; float ay = y * cellHeight + domain.lowerBound.y; CxFastList <FVector2> bp = p.GeomP.Points; CxFastList <FVector2> ap = u.GeomP.Points; //skip if it's already been combined with above polygon if (u.GeomP == p.GeomP) { x++; continue; } //combine above (but disallow the hole thingies CxFastListNode <FVector2> bi = bp.Begin(); while (Square(bi.Elem().Y - ay) > Box2D.Settings.b2_epsilon || bi.Elem().X < ax) { bi = bi.Next(); } //NOTE: Unused //Vector2 b0 = bi.elem(); FVector2 b1 = bi.Next().Elem(); if (Square(b1.Y - ay) > Box2D.Settings.b2_epsilon) { x++; continue; } bool brk = true; CxFastListNode <FVector2> ai = ap.Begin(); while (ai != ap.End()) { if (VecDsq(ai.Elem(), b1) < Box2D.Settings.b2_epsilon) { brk = false; break; } ai = ai.Next(); } if (brk) { x++; continue; } CxFastListNode <FVector2> bj = bi.Next().Next(); if (bj == bp.End()) { bj = bp.Begin(); } while (bj != bi) { ai = ap.Insert(ai, bj.Elem()); // .clone() bj = bj.Next(); if (bj == bp.End()) { bj = bp.Begin(); } u.GeomP.Length++; } //u.p.simplify(float.Epsilon,float.Epsilon); // ax = x + 1; while (ax < xn) { GeomPolyVal p2 = ps[(int)ax, y]; if (p2 == null || p2.GeomP != p.GeomP) { ax++; continue; } p2.GeomP = u.GeomP; ax++; } ax = x - 1; while (ax >= 0) { GeomPolyVal p2 = ps[(int)ax, y]; if (p2 == null || p2.GeomP != p.GeomP) { ax--; continue; } p2.GeomP = u.GeomP; ax--; } ret.Remove(p.GeomP); p.GeomP = u.GeomP; x = (int)((bi.Next().Elem().X - domain.lowerBound.x) / cellWidth) + 1; //x++; this was already commented out! } } polyList = ret.GetListOfElements(); foreach (GeomPoly poly in polyList) { verticesList.Add(new Vertices(poly.Points.GetListOfElements())); } return(verticesList); }
/// <summary> /// Get all intersections between a line segment and an AABB. /// </summary> /// <param name="point1">The first point of the line segment to test</param> /// <param name="point2">The second point of the line segment to test.</param> /// <param name="aabb">The AABB that is used for testing intersection.</param> /// <param name="intersectionPoints">An list of intersection points. Any intersection points found will be added to this list.</param> public static void LineSegmentAABBIntersect(ref FVector2 point1, ref FVector2 point2, Box2D.AABB aabb, ref List <FVector2> intersectionPoints) { // LineSegmentVerticesIntersect(ref point1, ref point2, aabb.vVertices, ref intersectionPoints); }