示例#1
0
        public static void general_intersections()
        {
            var line = new Line2(new Point2(2, 1), new Vector2(2, 1));

            line.Intersects(new Point2(-2, -1)).Should().BeTrue();
            line.Intersects(new Point2(0, 0)).Should().BeTrue();
            line.Intersects(new Point2(1, 0.5)).Should().BeTrue();
            line.Intersects(new Point2(2, 1)).Should().BeTrue();
            line.Intersects(new Point2(4, 2)).Should().BeTrue();
            line.Intersects(new Point2(1, 2)).Should().BeFalse();
        }
示例#2
0
        public static void line_ray_basic_intersection_testing()
        {
            var a = new Line2(new Point2(3, 3), new Vector2(1, 1));
            var b = new Ray2(new Point2(0, 1), new Vector2(0, 1));
            var c = new Ray2(new Point2(2, 2), new Vector2(-1, -1));
            var d = new Ray2(new Point2(2, 3), new Vector2(-1, -1));

            a.Intersects(b.GetReverse()).Should().BeTrue();
            a.Intersects(c).Should().BeTrue();
            a.Intersects(c.GetReverse()).Should().BeTrue();
            a.Intersects(b).Should().BeFalse();
            a.Intersects(d).Should().BeFalse();
            a.Intersects(d.GetReverse()).Should().BeFalse();
        }
示例#3
0
        public static void line_line_basic_intersection_testing()
        {
            var a = new Line2(new Point2(3, 3), new Vector2(1, 1));
            var b = new Line2(new Point2(0, 1), new Vector2(0, 1));
            var c = new Line2(new Point2(2, 2), new Vector2(-1, -1));
            var d = new Line2(new Point2(2, 3), new Vector2(-1, -1));
            var e = new Line2(new Point2(2, 3), new Vector2(-2, -2));
            var f = new Line2(new Point2(2, 3), new Vector2(0.5, 0.5));

            a.Intersects(a).Should().BeTrue();
            a.Intersects(b).Should().BeTrue();
            a.Intersects(c).Should().BeTrue();
            a.Intersects(d).Should().BeFalse();
            a.Intersects(e).Should().BeFalse();
            a.Intersects(f).Should().BeFalse();
        }
示例#4
0
        private Circle2 FitCirleToThreePoints(IVector2 p1, IVector2 p2, IVector2 p3)
        {
            try
            {
                double x1           = (p1.X + p2.X) / 2.0;
                double y1           = (p1.Y + p2.Y) / 2.0;
                double dy1          = p2.X - p1.X;
                double dx1          = -1 * (p2.Y - p1.Y);
                double x2           = (p3.X + p2.X) / 2.0;
                double y2           = (p3.Y + p2.Y) / 2.0;
                double dy2          = p3.X - p2.X;
                double dx2          = -1 * (p3.Y - p2.Y);
                var    line1        = new Line2(new Vector2(x1, y1), new Vector2(x1 + dx1, y1 + dy1));
                var    line2        = new Line2(new Vector2(x2, y2), new Vector2(x2 + dx2, y2 + dy2));
                var    intersection = line1.Intersects(line2);
                if (!(intersection.Intersects))
                {
                    throw new Exception("Points are colinear, Couldn't find arc");
                }
                else
                {
                    var center = new Vector2(intersection.Point.X, intersection.Point.Y);

                    var dx = center.X - p1.X;
                    var dy = center.Y - p1.Y;
                    var r  = Math.Sqrt(dx * dx + dy * dy);
                    if (double.IsNaN(center.X) || double.IsNaN(center.Y) || double.IsNaN(r))
                    {
                        throw new ArgumentException("Unable to calculate center or radius of fitting circle");
                    }
                    return(new Circle2(center, r));
                }
            }
            catch (Exception)
            {
                throw;
            }
        }
示例#5
0
        /// <summary>
        /// Draws the area between two curves using the provided color.
        /// </summary>
        /// <param name="curves">Curves to draw within the currently set range.</param>
        /// <param name="color">Color to draw the area with.</param>
        private void DrawCurveRange(EdAnimationCurve[] curves, Color color)
        {
            float range = GetRange(true);

            if (curves.Length != 2 || curves[0] == null || curves[1] == null)
            {
                return;
            }

            KeyFrame[][] keyframes = { curves[0].KeyFrames, curves[1].KeyFrames };
            if (keyframes[0].Length <= 0 || keyframes[1].Length <= 0)
            {
                return;
            }

            int   numSamples    = (drawableWidth + LINE_SPLIT_WIDTH - 1) / LINE_SPLIT_WIDTH;
            float timePerSample = range / numSamples;

            float time           = rangeOffset;
            float lengthPerPixel = rangeLength / drawableWidth;

            time -= lengthPerPixel * PADDING;

            int[] keyframeIndices = { 0, 0 };

            // Find first valid keyframe indices
            for (int curveIdx = 0; curveIdx < 2; curveIdx++)
            {
                keyframeIndices[curveIdx] = keyframes[curveIdx].Length;

                for (int i = 0; i < keyframes[curveIdx].Length; i++)
                {
                    if (keyframes[curveIdx][i].time > time)
                    {
                        keyframeIndices[curveIdx] = i;
                    }
                }
            }

            List <float> times = new List <float>();

            List <float>[] points = { new List <float>(), new List <float>() };

            // Determine start points
            for (int curveIdx = 0; curveIdx < 2; curveIdx++)
            {
                float value = curves[curveIdx].Evaluate(time, false);
                points[curveIdx].Add(value);
            }

            times.Add(time);

            float rangeEnd = rangeOffset + range;

            while (time < rangeEnd)
            {
                float nextTime = time + timePerSample;
                bool  hasStep  = false;

                // Determine time to sample at. Use fixed increments unless there's a step keyframe within our increment in
                // which case we use its time so we can evaluate it directly
                for (int curveIdx = 0; curveIdx < 2; curveIdx++)
                {
                    int keyframeIdx = keyframeIndices[curveIdx];
                    if (keyframeIdx < keyframes[curveIdx].Length)
                    {
                        KeyFrame keyframe = keyframes[curveIdx][keyframeIdx];

                        bool isStep = keyframe.inTangent == float.PositiveInfinity ||
                                      keyframe.outTangent == float.PositiveInfinity;

                        if (isStep && keyframe.time <= nextTime)
                        {
                            nextTime = Math.Min(nextTime, keyframe.time);
                            hasStep  = true;
                        }
                    }
                }

                // Evaluate
                if (hasStep)
                {
                    for (int curveIdx = 0; curveIdx < 2; curveIdx++)
                    {
                        int keyframeIdx = keyframeIndices[curveIdx];
                        if (keyframeIdx < keyframes[curveIdx].Length)
                        {
                            KeyFrame keyframe = keyframes[curveIdx][keyframeIdx];

                            if (MathEx.ApproxEquals(keyframe.time, nextTime))
                            {
                                if (keyframeIdx > 0)
                                {
                                    KeyFrame prevKeyframe = keyframes[curveIdx][keyframeIdx - 1];
                                    points[curveIdx].Add(prevKeyframe.value);
                                }
                                else
                                {
                                    points[curveIdx].Add(keyframe.value);
                                }

                                points[curveIdx].Add(keyframe.value);
                            }
                            else
                            {
                                // The other curve has step but this one doesn't, we just insert the same value twice
                                float value = curves[curveIdx].Evaluate(nextTime, false);
                                points[curveIdx].Add(value);
                                points[curveIdx].Add(value);
                            }

                            times.Add(nextTime);
                            times.Add(nextTime);
                        }
                    }
                }
                else
                {
                    for (int curveIdx = 0; curveIdx < 2; curveIdx++)
                    {
                        points[curveIdx].Add(curves[curveIdx].Evaluate(nextTime, false));
                    }

                    times.Add(nextTime);
                }

                // Advance keyframe indices
                for (int curveIdx = 0; curveIdx < 2; curveIdx++)
                {
                    int keyframeIdx = keyframeIndices[curveIdx];
                    while (keyframeIdx < keyframes[curveIdx].Length)
                    {
                        KeyFrame keyframe = keyframes[curveIdx][keyframeIdx];
                        if (keyframe.time > nextTime)
                        {
                            break;
                        }

                        keyframeIdx = ++keyframeIndices[curveIdx];
                    }
                }

                time = nextTime;
            }

            // End points
            for (int curveIdx = 0; curveIdx < 2; curveIdx++)
            {
                float value = curves[curveIdx].Evaluate(rangeEnd, false);
                points[curveIdx].Add(value);
            }

            times.Add(rangeEnd);

            int             numQuads = times.Count - 1;
            List <Vector2I> vertices = new List <Vector2I>();

            for (int i = 0; i < numQuads; i++)
            {
                int idxLeft  = points[0][i] < points[1][i] ? 0 : 1;
                int idxRight = points[0][i + 1] < points[1][i + 1] ? 0 : 1;

                Vector2[] left =
                {
                    new Vector2(times[i], points[0][i]),
                    new Vector2(times[i], points[1][i])
                };

                Vector2[] right =
                {
                    new Vector2(times[i + 1], points[0][i + 1]),
                    new Vector2(times[i + 1], points[1][i + 1])
                };

                if (idxLeft == idxRight)
                {
                    int idxA = idxLeft;
                    int idxB = (idxLeft + 1) % 2;

                    vertices.Add(CurveToPixelSpace(left[idxB]));
                    vertices.Add(CurveToPixelSpace(right[idxB]));
                    vertices.Add(CurveToPixelSpace(left[idxA]));

                    vertices.Add(CurveToPixelSpace(right[idxB]));
                    vertices.Add(CurveToPixelSpace(right[idxA]));
                    vertices.Add(CurveToPixelSpace(left[idxA]));
                }
                // Lines intersects, can't represent them with a single quad
                else if (idxLeft != idxRight)
                {
                    int idxA = idxLeft;
                    int idxB = (idxLeft + 1) % 2;

                    Line2 lineA = new Line2(left[idxB], right[idxA] - left[idxB]);
                    Line2 lineB = new Line2(left[idxA], right[idxB] - left[idxA]);

                    if (lineA.Intersects(lineB, out var t))
                    {
                        Vector2 intersection = left[idxB] + t * (right[idxA] - left[idxB]);

                        vertices.Add(CurveToPixelSpace(left[idxB]));
                        vertices.Add(CurveToPixelSpace(intersection));
                        vertices.Add(CurveToPixelSpace(left[idxA]));

                        vertices.Add(CurveToPixelSpace(intersection));
                        vertices.Add(CurveToPixelSpace(right[idxB]));
                        vertices.Add(CurveToPixelSpace(right[idxA]));
                    }
                }
            }

            canvas.DrawTriangleList(vertices.ToArray(), color, 129);
        }
示例#6
0
        private static List <Triangle> Cut(Triangle tri, Line3 line)
        {
            // Create coordinate system
            Vec3 norm  = tri.Normal;
            Vec3 xaxis = tri.Edge13.Normalized;
            Vec3 yaxis = Vec3.Cross(norm, xaxis);

            // Convert to 2d space
            Vec2 v1 = Vec2.Zero;                                     // Consider point 0 the origin
            Vec2 v2 = Collapse(tri.Item2 - tri.Item1, xaxis, yaxis); // Relative position of Item2
            Vec2 v3 = Collapse(tri.Item3 - tri.Item1, xaxis, yaxis); // Relative position of Item3

            Vec2 ls = Collapse(line.Item1 - tri.Item1, xaxis, yaxis);
            Vec2 le = Collapse(line.Item2 - tri.Item1, xaxis, yaxis);

            Line2 l12 = new Line2(v1, v2);
            Line2 l13 = new Line2(v1, v3);
            Line2 l23 = new Line2(v2, v3);

            Line2 cut = new Line2(ls, le);

            // Perform intersection test
            double k12, k13, k23;
            double c12, c13, c23;
            bool   i12 = l12.Intersects(cut, out c12, out k12);
            bool   i13 = l13.Intersects(cut, out c13, out k13);
            bool   i23 = l23.Intersects(cut, out c23, out k23);

            // Check cases
            List <Triangle> tris = new List <Triangle>();

            // Corner - Edge intersection (3 cases)
            if (IsCorner(c12, c13) && IsEdge(c23))
            {
                // Crossing from corner 1 to edge 2->3
                Vec3 midpoint = Vec3.Lerp(tri.Item2, tri.Item3, c23);
                tris.Add(new Triangle(tri.Item1, tri.Item2, midpoint));
                tris.Add(new Triangle(tri.Item1, midpoint, tri.Item3));
                return(tris);
            }
            else if (IsCorner(c13, c23) && IsEdge(c12))
            {
                // Crossing from corner 3 to edge 1->2
                Vec3 midpoint = Vec3.Lerp(tri.Item1, tri.Item2, c12);
                tris.Add(new Triangle(tri.Item1, midpoint, tri.Item3));
                tris.Add(new Triangle(midpoint, tri.Item2, tri.Item3));
                return(tris);
            }
            else if (IsCorner(c12, c23) && IsEdge(c13))
            {
                // Crossing from corner 2 to edge 1->3
                Vec3 midpoint = Vec3.Lerp(tri.Item1, tri.Item3, c13);
                tris.Add(new Triangle(tri.Item1, tri.Item2, midpoint));
                tris.Add(new Triangle(midpoint, tri.Item2, tri.Item3));
                return(tris);
            }
            // Edge - Edge intersection (3 cases)
            else if (IsEdge(c12) && IsEdge(c23))
            {
                // Collision crossing 1->2, 2->3
                Vec3 m1  = Vec3.Lerp(tri.Item1, tri.Item2, c12);
                Vec3 m2  = Vec3.Lerp(tri.Item2, tri.Item3, c23);
                Vec3 mid = (tri.Item1 + tri.Item3) / 2;

                tris.Add(new Triangle(tri.Item1, m1, mid));
                tris.Add(new Triangle(m1, m2, mid));
                tris.Add(new Triangle(mid, m2, tri.Item3));

                tris.Add(new Triangle(m1, tri.Item2, m2));
                return(tris);
            }
            else if (IsEdge(c12) && IsEdge(c13))
            {
                // Collision crossing 1->3, 1->2
                Vec3 m1  = Vec3.Lerp(tri.Item1, tri.Item2, c12);
                Vec3 m2  = Vec3.Lerp(tri.Item1, tri.Item3, c13);
                Vec3 mid = (tri.Item2 + tri.Item3) / 2;

                tris.Add(new Triangle(m1, tri.Item2, mid));
                tris.Add(new Triangle(m1, mid, m2));
                tris.Add(new Triangle(m2, mid, tri.Item3));

                tris.Add(new Triangle(tri.Item1, m1, m2));
                return(tris);
            }
            else if (IsEdge(c13) && IsEdge(c23))
            {
                // Collision crossing 1->3, 2->3
                Vec3 m1  = Vec3.Lerp(tri.Item1, tri.Item3, c13);
                Vec3 m2  = Vec3.Lerp(tri.Item2, tri.Item3, c23);
                Vec3 mid = (tri.Item1 + tri.Item2) / 2;

                tris.Add(new Triangle(mid, tri.Item2, m2));
                tris.Add(new Triangle(mid, m2, m1));
                tris.Add(new Triangle(tri.Item1, mid, m1));

                tris.Add(new Triangle(m1, m2, tri.Item3));
                return(tris);
            }
            // No intersection (1 case)
            else
            {
                tris.Add(tri);
                return(tris);
            }
        }
示例#7
0
        public static void general_intersections() {
            var line = new Line2(new Point2(2, 1), new Vector2(2, 1));

            line.Intersects(new Point2(-2, -1)).Should().BeTrue();
            line.Intersects(new Point2(0, 0)).Should().BeTrue();
            line.Intersects(new Point2(1, 0.5)).Should().BeTrue();
            line.Intersects(new Point2(2, 1)).Should().BeTrue();
            line.Intersects(new Point2(4, 2)).Should().BeTrue();
            line.Intersects(new Point2(1, 2)).Should().BeFalse();
        }
示例#8
0
        public static void line_ray_basic_intersection_testing() {
            var a = new Line2(new Point2(3, 3), new Vector2(1, 1));
            var b = new Ray2(new Point2(0, 1), new Vector2(0, 1));
            var c = new Ray2(new Point2(2, 2), new Vector2(-1, -1));
            var d = new Ray2(new Point2(2, 3), new Vector2(-1, -1));

            a.Intersects(b.GetReverse()).Should().BeTrue();
            a.Intersects(c).Should().BeTrue();
            a.Intersects(c.GetReverse()).Should().BeTrue();
            a.Intersects(b).Should().BeFalse();
            a.Intersects(d).Should().BeFalse();
            a.Intersects(d.GetReverse()).Should().BeFalse();
        }
示例#9
0
        public static void line_line_basic_intersection_testing() {
            var a = new Line2(new Point2(3, 3), new Vector2(1, 1));
            var b = new Line2(new Point2(0, 1), new Vector2(0, 1));
            var c = new Line2(new Point2(2, 2), new Vector2(-1, -1));
            var d = new Line2(new Point2(2, 3), new Vector2(-1, -1));
            var e = new Line2(new Point2(2, 3), new Vector2(-2, -2));
            var f = new Line2(new Point2(2, 3), new Vector2(0.5, 0.5));

            a.Intersects(a).Should().BeTrue();
            a.Intersects(b).Should().BeTrue();
            a.Intersects(c).Should().BeTrue();
            a.Intersects(d).Should().BeFalse();
            a.Intersects(e).Should().BeFalse();
            a.Intersects(f).Should().BeFalse();
        }