/// <summary> /// Smallest cell that contains given box. /// </summary> public Cell2d(Box2d box) { if (!box.IsValid) { throw new InvalidOperationException(); } // case 1: contains origin if (box.Min.X < 0.0 && box.Max.X > 0.0 || box.Min.Y < 0.0 && box.Max.Y > 0.0) { X = Y = long.MaxValue; Exponent = Math.Max(box.Min.NormMax, box.Max.NormMax).Log2Int() + 1; } else // case 2: doesn't contain origin { Exponent = (box.Min == box.Max) ? (box.Min.NormMax / (long.MaxValue >> 1)).Log2Int() : box.Size.NormMax.Log2Int() ; var s = Math.Pow(2.0, Exponent); var a = (box.Min / s).Floor() * s; while (a.X + s < box.Max.X || a.Y + s < box.Max.Y) { s *= 2.0; Exponent++; a = (box.Min / s).Floor() * s; } X = (long)Math.Floor(a.X / s); Y = (long)Math.Floor(a.Y / s); } }
public static IEnumerable <Polygon2d> Union(this Box2d b0, Box2d b1) { Polygon2d p0 = new Polygon2d(b0.ComputeCornersCCW()); Polygon2d p1 = new Polygon2d(b1.ComputeCornersCCW()); return(p0.Union(p1)); }
private static Box2d ComputeBoundingBox(long x, long y, int e) { var d = Math.Pow(2.0, e); var isCenteredAtOrigin = x == long.MaxValue && y == long.MaxValue; var min = isCenteredAtOrigin ? new V2d(-0.5 * d) : new V2d(x * d, y * d); return(Box2d.FromMinAndSize(min, new V2d(d, d))); }
/// <summary> /// Gets oriented bounding box of this polygon /// </summary> public static Polygon2d ComputeOrientedBoundingBox(this Polygon2d polygon) { var rot = polygon.ComputeMinAreaEnclosingBoxRotation(); var rotInv = rot.Transposed; var bbGlobal = new Box2d(polygon.Points.Select(p => rot * p)); return(new Polygon2d(bbGlobal.ComputeCornersCCW().Apply(p => rotInv * p))); }
public Hull2d(Box2d box) { PlaneArray = new[] { new Plane2d(V2d.XAxis, box.Min), new Plane2d(V2d.YAxis, box.Min), new Plane2d(-V2d.XAxis, box.Max), new Plane2d(-V2d.YAxis, box.Max), }; }
/// <summary> /// Compute the Delaunay triangluation of the supplied points. Note that /// the supplied point array must be by 3 larger than the actual number of /// points. /// </summary> private static void Triangulate2d(V2d[] pa, out Triangle1i[] ta, out int triangleCount) { int vc = pa.Length - 4; int tcMax = 2 * vc + 2; // sharp upper bound with no degenerates int ecMax = 6 * vc - 3; // sharp bound: last step replaces all tris ta = new Triangle1i[tcMax]; var ra = new double[tcMax]; var ca = new V2d[tcMax]; var ea = new Line1i[ecMax]; // -------------------------------------- set up the supertriangle ta[0] = new Triangle1i(vc, vc + 2, vc + 1); ra[0] = -1.0; ta[1] = new Triangle1i(vc, vc + 3, vc + 2); ra[1] = -1.0; int tc = 2, cc = 0; // triangle count, complete count // ------------- superquad vertices at the end of vertex array var box = new Box2d(pa.Take(vc)).EnlargedBy(0.1); V2d center = box.Center, size = box.Size; pa[vc + 0] = box.Min; pa[vc + 1] = new V2d(box.Min.X, box.Max.Y); pa[vc + 2] = box.Max; pa[vc + 3] = new V2d(box.Max.X, box.Min.Y); // ------------------------------ include the points one at a time for (int i = 0; i < vc; i++) { V2d p = pa[i]; int ec = 0; /* * if the point lies inside the circumcircle then the triangle * is removed and its edges are added to the edge array */ for (int ti = cc; ti < tc; ti++) { var tr = ta[ti]; double r2 = ra[ti]; if (r2 < 0.0) { Triangle2d.ComputeCircumCircleSquared( pa[tr.I0], pa[tr.I1], pa[tr.I2], out center, out r2); ra[ti] = r2; ca[ti] = center; } else { center = ca[ti]; } // ---------------- include this if points are sorted by X if (center.X < p.X && (p.X - center.X).Square() > r2) { Fun.Swap(ref ta[ti], ref ta[cc]); ra[ti] = ra[cc]; ca[ti] = ca[cc]; ++cc; continue; } if (Vec.DistanceSquared(p, center) <= r2) { int nec = ec + 3; if (nec >= ecMax) { ecMax = Fun.Max(nec, (int)(1.1 * (double)ecMax)); Array.Resize(ref ea, ecMax); } ea[ec] = tr.Line01; ea[ec + 1] = tr.Line12; ea[ec + 2] = tr.Line20; --tc; ec = nec; ta[ti] = ta[tc]; ra[ti] = ra[tc]; ca[ti] = ca[tc]; --ti; } } // ---------------------------------------- tag multiple edges for (int ei = 0; ei < ec - 1; ei++) { for (int ej = ei + 1; ej < ec; ej++) { if (ea[ei].I0 == ea[ej].I1 && ea[ei].I1 == ea[ej].I0) { ea[ei] = Line1i.Invalid; ea[ej] = Line1i.Invalid; } } } // ------------------ form new triangles for the current point for (int ei = 0; ei < ec; ei++) { var e = ea[ei]; if (e.I0 < 0 || e.I1 < 0) { continue; // skip tagged edges } if (tc >= tcMax) // necessary for degenerate cases { tcMax = Fun.Max(tcMax + 1, (int)(1.1 * (double)tcMax)); Array.Resize(ref ta, tcMax); Array.Resize(ref ra, tcMax); Array.Resize(ref ca, tcMax); } ta[tc] = new Triangle1i(e.I0, e.I1, i); ra[tc++] = -1.0; } } // ------------------ remove triangles with supertriangle vertices for (int ti = 0; ti < tc; ti++) { if (ta[ti].I0 >= vc || ta[ti].I1 >= vc || ta[ti].I2 >= vc) { ta[ti--] = ta[--tc]; } } triangleCount = tc; }
/// <summary> /// Computes bounding circle of box. /// </summary> public static Circle2d GetBoundingCircle2d(this Box2d box) => box.IsInvalid ? Circle2d.Invalid : new Circle2d(box.Center, 0.5 * box.Size.Length);
public static V2d UniformV2dFullClosed(this IRandomUniform rnd, Box2d box) { return(new V2d(box.Min.X + rnd.UniformDoubleFullClosed() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformDoubleFullClosed() * (box.Max.Y - box.Min.Y))); }
/// <summary> /// This variant of the intersection method returns the affected /// planes of the box if the box was hit. /// </summary> public bool Intersects( Box2d box, ref double tmin, ref double tmax, out Box.Flags tminFlags, out Box.Flags tmaxFlags ) { var dirFlags = DirFlags; tminFlags = Box.Flags.None; tmaxFlags = Box.Flags.None; if ((dirFlags & DirFlags.PositiveX) != 0) { { double t = (box.Max.X - Ray.Origin.X) * InvDir.X; if (t <= tmin) { return(false); } if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxX; } } { double t = (box.Min.X - Ray.Origin.X) * InvDir.X; if (t >= tmax) { return(false); } if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinX; } } } else if ((dirFlags & DirFlags.NegativeX) != 0) { { double t = (box.Min.X - Ray.Origin.X) * InvDir.X; if (t <= tmin) { return(false); } if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinX; } } { double t = (box.Max.X - Ray.Origin.X) * InvDir.X; if (t >= tmax) { return(false); } if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxX; } } } else // ray parallel to X-plane { if (Ray.Origin.X < box.Min.X || Ray.Origin.X > box.Max.X) { return(false); } } if ((dirFlags & DirFlags.PositiveY) != 0) { { double t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y; if (t <= tmin) { return(false); } if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxY; } } { double t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y; if (t >= tmax) { return(false); } if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinY; } } } else if ((dirFlags & DirFlags.NegativeY) != 0) { { double t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y; if (t <= tmin) { return(false); } if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinY; } } { double t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y; if (t >= tmax) { return(false); } if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxY; } } } else // ray parallel to Y-plane { if (Ray.Origin.Y < box.Min.Y || Ray.Origin.Y > box.Max.Y) { return(false); } } if (tmin > tmax) { return(false); } return(true); }
public Box2f(Box2d box) { Min = (V2f)box.Min; Max = (V2f)box.Max; }
public OrientedBox2d(Box2d box, Euclidean2d trafo) { Box = box; Trafo = trafo; }
public OrientedBox2d(Box2d box, V2d trans) { Box = box; Trafo = new Euclidean2d(Rot2d.Identity, trans); }
public OrientedBox2d(Box2d box, Rot2d rot) { Box = box; Trafo = new Euclidean2d(rot, V2d.Zero); }
/// <summary> /// Rasterizes an array of polygons into a matrix of given size. /// First polygon is rasterized with label 1, second polygon with label 2, and so on. /// </summary> /// <param name="polygons">Polygons to rasterize.</param> /// <param name="resolution">Resolution of result matrix.</param> /// <param name="bb"></param> public static Matrix <int> RasterizeAsLabels(this IEnumerable <Polygon2d> polygons, V2i resolution, Box2d bb) { var matrix = new Matrix <int>(resolution); var scale = (V2d)resolution / bb.Size; int i = 1; foreach (var poly in polygons) { RasterizePolygon(poly.ToPolygon2d(p => (p - bb.Min) * scale), matrix, i++); } return(matrix); }
public static Polygon2d ToPolygon2dCCW(this Box2d self) => new Polygon2d(self.Min, new V2d(self.Max.X, self.Min.Y), self.Max, new V2d(self.Min.X, self.Max.Y));
public SampleGrid2d(V2l gridSize, Box2d region) { m_last = gridSize - new V2l(1, 1); m_region = region; m_delta = region.Size / (V2d)m_last; }