private static void InsertEntrances(InDoorGeneratorSettings settings, Floor floor, List <SkeletonEdge> walls) { var footprint = settings.Footprint; // doors are not set if (settings.Doors == null) { FindDoorPosition(settings); } foreach (var door in settings.Doors) { var start = footprint[door.Key]; var end = footprint[(door.Key + 1) % footprint.Count]; var centerOffset = door.Value; var vec = (end - start).Normalized(); var startOfDoor = start + vec * (centerOffset - settings.HalfTransitAreaWidth); var endOfDoor = start + vec * (centerOffset + settings.HalfTransitAreaWidth); floor.Entrances.Add(new LineSegment2d(startOfDoor, endOfDoor)); var centerOfDoor = start + vec * centerOffset; vec.Negate(); var doorRay = new LineParametric2d(centerOfDoor, Vector2dUtils.OrthogonalRight(vec)); InsertEntrance(settings, walls, doorRay, centerOffset + settings.HalfTransitAreaWidth); } }
public Vertex(Vector2d point, double distance, LineParametric2d bisector, Edge previousEdge, Edge nextEdge) { Point = point; Distance = Math.Round(distance, RoundDigitCount); Bisector = bisector; PreviousEdge = previousEdge; NextEdge = nextEdge; IsProcessed = false; }
public static Vector2d Collide(LineParametric2d ray, LineLinear2d line, double epsilon) { var collide = LineLinear2d.Collide(ray.CreateLinearForm(), line); if (collide.Equals(Vector2d.Empty)) { return(Vector2d.Empty); } var collideVector = collide - ray.A; return(ray.U.Dot(collideVector) < epsilon ? Vector2d.Empty : collide); }
private static void InsertEntrance(InDoorGeneratorSettings settings, List <SkeletonEdge> walls, LineParametric2d ray, double minimalSideSize) { var doorEdge = default(SkeletonEdge); var distance = double.MaxValue; var intersectPoint = Vector2d.Empty; int i = -1; foreach (var edge in walls) { i++; if (edge.IsOuter && !edge.IsSkeleton) { continue; } var currIntersect = LineParametric2d.Collide(ray, edge.Line, 0.00001); if (currIntersect == Vector2d.Empty || !Vector2dUtils.IsPointOnSegment(edge.Start, edge.End, currIntersect)) { continue; } var currDistance = currIntersect.DistanceTo(ray.A); if (distance > currDistance /* && currDistance > minimalSideSize*/) { doorEdge = edge; distance = currDistance; intersectPoint = currIntersect; } } var startDist = Math.Min(distance, settings.Skeleton.Distances[doorEdge.Start]); var endDistance = Math.Min(distance, settings.Skeleton.Distances[doorEdge.End]); walls.Add(new SkeletonEdge(doorEdge.Start, intersectPoint, false, startDist, settings.HalfTransitAreaWidth)); walls.Add(new SkeletonEdge(intersectPoint, doorEdge.End, false, endDistance, settings.HalfTransitAreaWidth)); walls.Add(new SkeletonEdge(ray.A, intersectPoint, false, distance, settings.HalfTransitAreaWidth)); }
public static bool IsPointOnRay(Vector2d point, LineParametric2d ray, double epsilon) { var rayDirection = new Vector2d(ray.U).Normalized(); // test if point is on ray var pointVector = point - ray.A; var dot = rayDirection.Dot(pointVector); if (dot < epsilon) { return(false); } var x = rayDirection.X; rayDirection.X = rayDirection.Y; rayDirection.Y = -x; dot = rayDirection.Dot(pointVector); return(-epsilon < dot && dot < epsilon); }
/// <summary> /// Calculate intersection points for rays. It can return more then one /// intersection point when rays overlaps. /// <see href="http://geomalgorithms.com/a05-_intersect-1.html" /> /// <see href="http://softsurfer.com/Archive/algorithm_0102/algorithm_0102.htm" /> /// </summary> /// <returns>class with intersection points. It never return null.</returns> public static IntersectPoints IntersectRays2D(LineParametric2d r1, LineParametric2d r2) { var s1p0 = r1.A; var s1p1 = r1.A + r1.U; var s2p0 = r2.A; var u = r1.U; var v = r2.U; var w = s1p0 - s2p0; var d = Perp(u, v); // test if they are parallel (includes either being a point) if (Math.Abs(d) < SmallNum) { // they are NOT collinear // S1 and S2 are parallel if (Perp(u, w) != 0 || Perp(v, w) != 0) { return(Empty); } // they are collinear or degenerate // check if they are degenerate points var du = Dot(u, u); var dv = Dot(v, v); if (du == 0 && dv == 0) { // both segments are points if (s1p0 != s2p0) { return(Empty); } // they are the same point return(new IntersectPoints(s1p0)); } if (du == 0) { // S1 is a single point if (!InCollinearRay(s1p0, s2p0, v)) { return(Empty); } return(new IntersectPoints(s1p0)); } if (dv == 0) { // S2 a single point if (!InCollinearRay(s2p0, s1p0, u)) { return(Empty); } return(new IntersectPoints(s2p0)); } // they are collinear segments - get overlap (or not) double t0, t1; // endpoints of S1 in eqn for S2 var w2 = s1p1 - s2p0; if (v.X != 0) { t0 = w.X / v.X; t1 = w2.X / v.X; } else { t0 = w.Y / v.Y; t1 = w2.Y / v.Y; } if (t0 > t1) { // must have t0 smaller than t1 var t = t0; t0 = t1; t1 = t; // swap if not } if (t1 < 0) { // NO overlap return(Empty); } // clip to min 0 t0 = t0 < 0 ? 0 : t0; if (t0 == t1) { // intersect is a point var I0 = new Vector2d(v); I0 *= t0; I0 += s2p0; return(new IntersectPoints(I0)); } // they overlap in a valid subsegment // I0 = S2_P0 + t0 * v; var I_0 = new Vector2d(v); I_0 *= t0; I_0 += s2p0; // I1 = S2_P0 + t1 * v; var I1 = new Vector2d(v); I1 *= t1; I1 += s2p0; return(new IntersectPoints(I_0, I1)); } // the segments are skew and may intersect in a point // get the intersect parameter for S1 var sI = Perp(v, w) / d; if (sI < 0 /* || sI > 1 */) { return(Empty); } // get the intersect parameter for S2 var tI = Perp(u, w) / d; if (tI < 0 /* || tI > 1 */) { return(Empty); } // I0 = S1_P0 + sI * u; // compute S1 intersect point var IO = new Vector2d(u); IO *= sI; IO += s1p0; return(new IntersectPoints(IO)); }