private List <BuildingPrimitive> CreatePrimitives(BuildingStoryLayoutPlacementAlgorithm placementAlgorithm, int node) { var sg = placementAlgorithm.StoryGraph; var primitives = new List <BuildingPrimitive>(); var nodeScale = placementAlgorithm.HalfSizes[node].ToVector(); var mainCorridorScale = new Vector3(nodeScale.X, nodeScale.Y, BuildingConstants.CorridorHalfWidth + MathHelper.Eps5); var mainCorridor = new BuildingPrimitive(BuildingPrimitiveType.Rectangle, mainCorridorScale, Transform.Identity, true); primitives.Add(mainCorridor); foreach (var seg in uniqueSegments) { var forward = seg.Second - seg.First; var halfWidth = forward.Length() / 2; var center = (seg.First + seg.Second) / 2; var scale = new Vector3(halfWidth, 1, BuildingConstants.CorridorHalfWidth); var transform = new Transform(1, Quaternion.RotationToFrame(forward, Vector3.UnitY), center); primitives.Add(new BuildingPrimitive(BuildingPrimitiveType.Rectangle, scale, transform)); } foreach (var point in uniquePoints) { primitives.Add(new BuildingPrimitive(BuildingPrimitiveType.Circle, new Vector3(BuildingConstants.CorridorHalfWidth), Transform.Translation(point))); } foreach (var child in sg.Children[node]) { var scale = placementAlgorithm.HalfSizes[child].ToVector(); var pos = placementAlgorithm.RelativePositions[child]; if (!sg.Children[child].Any()) { scale.Z += BuildingConstants.CorridorHalfWidth / 2; pos.Z -= scale.Z - BuildingConstants.CorridorHalfWidth; } primitives.Add(new BuildingPrimitive(BuildingPrimitiveType.Rectangle, scale, Transform.Translation(pos))); } return(primitives); }
private static void GetExternalPart(LineSegment3 segment, BuildingPrimitive primitive, List <LineSegment3> results) { var invTransform = primitive.Transform.Invert(); var transformedSeg = new LineSegment3(segment.Point1 * invTransform, segment.Point2 * invTransform); var seg = new LineSegment2(transformedSeg.Point1.Xz, transformedSeg.Point2.Xz); if (primitive.Type == BuildingPrimitiveType.Rectangle) { var rect = new AaRectangle2(Vector2.Zero, primitive.Scale.X, primitive.Scale.Z); var conains1 = rect.ContainsPoint(seg.Point1); var conains2 = rect.ContainsPoint(seg.Point2); if (conains1 && conains2) { return; } if (!conains1 && !conains2) { var p = Vector2.Zero; int c = 0; foreach (var rectSegment in rect.GetSegments()) { var rsi = rectSegment.Intersect(seg); if (rsi.HasValue) { p += rsi.Value; c++; } } if (c > 0) { var t = ((p / c) - seg.Point1).Length() / (seg.Point2 - seg.Point1).Length(); var m = segment.Point1 + (segment.Point2 - segment.Point1) * t; GetExternalPart(new LineSegment3(segment.Point1, m), primitive, results); GetExternalPart(new LineSegment3(m, segment.Point2), primitive, results); return; } results.Add(segment); return; } var swap = conains1; if (swap) { CodingHelper.Swap(ref seg.Point1, ref seg.Point2); } var inter = seg.Intersect(new LineSegment2( new Vector2(-primitive.Scale.X, -primitive.Scale.Z), new Vector2(-primitive.Scale.X, primitive.Scale.Z))); if (inter.HasValue) { var rs1 = To3(seg.Point1, inter.Value, primitive.Transform, swap); results.Add(rs1); return; } inter = seg.Intersect(new LineSegment2( new Vector2(primitive.Scale.X, -primitive.Scale.Z), new Vector2(primitive.Scale.X, primitive.Scale.Z))); if (inter.HasValue) { var rs1 = To3(seg.Point1, inter.Value, primitive.Transform, swap); results.Add(rs1); return; } inter = seg.Intersect(new LineSegment2( new Vector2(-primitive.Scale.X, primitive.Scale.Z), new Vector2(primitive.Scale.X, primitive.Scale.Z))); if (inter.HasValue) { var rs1 = To3(seg.Point1, inter.Value, primitive.Transform, swap); results.Add(rs1); return; } inter = seg.Intersect(new LineSegment2( new Vector2(-primitive.Scale.X, -primitive.Scale.Z), new Vector2(primitive.Scale.X, -primitive.Scale.Z))); if (inter.HasValue) { var rs1 = To3(seg.Point1, inter.Value, primitive.Transform, swap); results.Add(rs1); return; } var rs2 = segment; results.Add(rs2); return; } else { var circle = new Circle2(Vector2.Zero, primitive.Scale.X); var conains1 = circle.Contains(seg.Point1); var conains2 = circle.Contains(seg.Point2); if (conains1 && conains2) { return; } if (!conains1 && !conains2) { var rs1 = segment; results.Add(rs1); return; } var swap = conains1; if (swap) { CodingHelper.Swap(ref seg.Point1, ref seg.Point2); } var dpp = seg.Point2 - seg.Point1; var dpc = seg.Point1; var a = dpp.LengthSquared(); var b = Vector2.Dot(dpp, dpc); var c = dpc.LengthSquared() - circle.Radius.Sq(); var discr = b * b - a * c; if (discr < 0) { results.Add(segment); return; } if (discr < MathHelper.Eps5) { results.Add(segment); return; //var l = -b / a; //if (0 <= l && l <= 1) } { var sqrdscr = MathHelper.Sqrt(discr); var l1 = (-b + sqrdscr) / a; var l2 = (-b - sqrdscr) / a; if (0 <= l1 && l1 <= 1) { var rs1 = To3(seg.Point1, Vector2.Lerp(seg.Point1, seg.Point2, l1), primitive.Transform, swap); results.Add(rs1); } if (0 <= l2 && l2 <= 1) { var rs1 = To3(seg.Point1, Vector2.Lerp(seg.Point1, seg.Point2, l2), primitive.Transform, swap); results.Add(rs1); } } } }