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); } }
private void DetectIntersectSegments(List <Vector2d> footprint, Vector2d start, Vector2d end, out Vector2d first, out int firstIndex, out Vector2d second, out int secondIndex) { firstIndex = -1; secondIndex = -1; first = default(Vector2d); second = default(Vector2d); for (int i = 0; i < footprint.Count; i++) { var p1 = footprint[i]; var p2 = footprint[i == footprint.Count - 1 ? 0 : i + 1]; double r; if (Vector2dUtils.LineIntersects(start, end, p1, p2, out r)) { var intersectionPoint = Vector2dUtils.GetPointAlongLine(p1, p2, r); if (firstIndex == -1) { firstIndex = i; first = intersectionPoint; } else { secondIndex = i; second = intersectionPoint; break; } } } }
/// <summary> Tries to find intersection with transit walls. </summary> private static bool HasIntersectPoint(List <Wall> extrudedWalls, List <Wall> connectedSkeletonWalls, Vector2d p1, Vector2d p2, out Vector2d intersectPoint, out int transitWallIndex) { intersectPoint = new Vector2d(); transitWallIndex = -1; var distance = double.MaxValue; for (var i = 0; i < extrudedWalls.Count; i++) { var wall = extrudedWalls[i]; if (wall.IsOuter) { continue; } var start = wall.Start; var end = wall.End; double r; if (!Vector2dUtils.LineIntersects(p1, p2, start, end, out r)) { continue; } var currIntersectPoint = new Vector2d( Math.Round(p1.X + (r * (p2.X - p1.X))), Math.Round((p1.Y + (r * (p2.Y - p1.Y))))); // skip intersections of skeleton edges which are connected with footprint var skip = false; foreach (var connectedWall in connectedSkeletonWalls) { if (Vector2dUtils.LineIntersects(p1, currIntersectPoint, connectedWall.Start, connectedWall.End, out r)) { skip = true; break; } } if (skip) { continue; } if (Vector2dUtils.IsPointOnSegment(start, end, currIntersectPoint)) { var currDistance = p1.DistanceTo(currIntersectPoint); if (currDistance > 0 && currDistance < distance) { intersectPoint = currIntersectPoint; transitWallIndex = i; distance = currDistance; } } } return(transitWallIndex != -1); }
private void FillMeshData(MeshData meshData, GradientWrapper gradient, float roofOffset, float roofHeight, List <Vector2d> footprint, Vector2d first, int firstIndex, Vector2d second, int secondIndex) { var meshIndex = (MultiPlaneMeshIndex)meshData.Index; var count = footprint.Count; int i = secondIndex; Vector2d startRidgePoint = default(Vector2d); do { var p1 = footprint[i]; var p2 = footprint[i == footprint.Count - 1 ? 0 : i + 1]; var nextIndex = i == count - 1 ? 0 : i + 1; // front faces if (i == firstIndex || i == secondIndex) { startRidgePoint = i == firstIndex ? first : second; var v0 = new Vector3((float)p1.X, roofOffset, (float)p1.Y); var v1 = new Vector3((float)startRidgePoint.X, roofHeight, (float)startRidgePoint.Y); var v2 = new Vector3((float)p2.X, roofOffset, (float)p2.Y); meshIndex.AddPlane(v0, v1, v2, meshData.NextIndex); AddTriangle(meshData, gradient, v0, v1, v2); i = nextIndex; continue; } // side faces Vector2d endRidgePoint; if (nextIndex == firstIndex || nextIndex == secondIndex) { endRidgePoint = nextIndex == firstIndex ? first : second; } else { endRidgePoint = Vector2dUtils.GetPointOnLine(first, second, p2); } // add trapezoid { var v0 = new Vector3((float)p1.X, roofOffset, (float)p1.Y); var v1 = new Vector3((float)p2.X, roofOffset, (float)p2.Y); var v2 = new Vector3((float)endRidgePoint.X, roofHeight, (float)endRidgePoint.Y); var v3 = new Vector3((float)startRidgePoint.X, roofHeight, (float)startRidgePoint.Y); meshIndex.AddPlane(v0, v1, v2, meshData.NextIndex); AddTriangle(meshData, gradient, v0, v2, v1); AddTriangle(meshData, gradient, v2, v0, v3); } startRidgePoint = endRidgePoint; i = nextIndex; } while (i != secondIndex); }
public void CanDetectIntersection() { // ARRANGE var s1 = new Vector2d(0, 0); var e1 = new Vector2d(10, 10); var s2 = new Vector2d(10, 0); var e2 = new Vector2d(0, 10); double r; // ACT var result = Vector2dUtils.LineIntersects(s1, e1, s2, e2, out r); var currIntersectPoint = Vector2dUtils.GetPointAlongLine(s1, s2, r); // ASSERT Assert.IsTrue(result); Assert.IsTrue(Math.Abs(currIntersectPoint.X - 5) < MathUtils.Epsion); Assert.IsTrue(Math.Abs(currIntersectPoint.X - 5) < MathUtils.Epsion); }
/// <summary> /// Inserts Vertical Access Area (VAA): stairs, elevators, etc. /// and merges it with corridors. /// </summary> private static List <List <IntPoint> > CreateTransitArea(InDoorGeneratorSettings settings, Floor floor, List <SkeletonEdge> walls, List <List <IntPoint> > transitPolygons) { foreach (var wall in walls) { if (wall.Size - settings.TransitAreaWidth > settings.VaaSizeWidth && wall.Distance > settings.VaaSizeHeight) { var startOfVaa1 = wall.Start + (wall.End - wall.Start).Normalized() * settings.HalfTransitAreaWidth; var orthogonalLeft = Vector2dUtils.OrthogonalLeft(wall.Start - wall.End).Normalized(); var endOfVaa1 = startOfVaa1 + orthogonalLeft * settings.VaaSizeHeight; var startOfVaa2 = startOfVaa1 + (wall.End - startOfVaa1).Normalized() * settings.VaaSizeWidth; var endOfVaa2 = startOfVaa2 + orthogonalLeft * settings.VaaSizeHeight; settings.Clipper.AddPath(new List <IntPoint> { new IntPoint(startOfVaa1.X * Scale, startOfVaa1.Y * Scale), new IntPoint(endOfVaa1.X * Scale, endOfVaa1.Y * Scale), new IntPoint(endOfVaa2.X * Scale, endOfVaa2.Y * Scale), new IntPoint(startOfVaa2.X * Scale, startOfVaa2.Y * Scale) }, PolyType.ptClip, true); floor.Stairs.Add(startOfVaa1); floor.Stairs.Add(endOfVaa1); floor.Stairs.Add(endOfVaa2); floor.Stairs.Add(startOfVaa2); break; } } settings.Clipper.AddPaths(transitPolygons, PolyType.ptSubject, true); var transitArea = new List <List <IntPoint> >(1); settings.Clipper.Execute(ClipType.ctUnion, transitArea); settings.Clipper.Clear(); return(transitArea); }
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 bool IsOnRightSite(Vector2d point, double epsilon) { var direction = point - A; return(Vector2dUtils.OrthogonalRight(U).Dot(direction) > -epsilon); }