예제 #1
0
        private static Vector3?Intersects(Ray3 ray, BuildingWallSegment wallSegment)
        {
            var height = ray.Point.Y;

            if (height < wallSegment.Basement.Point1.Y ||
                height > wallSegment.Basement.Point1.Y + wallSegment.Height)
            {
                return(null);
            }
            var ray2D     = new Ray2(ray.Point.Xz, ray.Direction.Xz.Normalize());
            var wallSeg2D = new LineSegment2(wallSegment.Basement.Point1.Xz, wallSegment.Basement.Point2.Xz);
            var inter2D   = wallSeg2D.Intersect(ray2D);

            if (!inter2D.HasValue)
            {
                return(null);
            }
            return(new Vector3(inter2D.Value.X, ray.Point.Y, inter2D.Value.Y));
        }
        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);
                    }
                }
            }
        }