Beispiel #1
0
        /// <summary>
        /// Constructs a nurbs curve representation of this arc.<br/>
        /// <em>Implementation of Algorithm A7.1 from The NURBS Book by Piegl and Tiller.</em>
        /// </summary>
        /// <returns>A nurbs curve shaped like this arc.</returns>
        internal void ToNurbs()
        {
            Vector3 axisX      = Plane.XAxis;
            Vector3 axisY      = Plane.YAxis;
            double  curveAngle = _domain.Length;
            int     numberOfArc;

            Point3[] pts;
            Point4[] ctrPts;
            double[] weights;

            // Number of arcs.
            double piNum = 0.5 * Math.PI;

            if ((curveAngle - piNum) <= GSharkMath.Epsilon)
            {
                numberOfArc = 1;
                pts         = new Point3[3];
                ctrPts      = new Point4[3];
                weights     = new double[3];
            }
            else if ((curveAngle - piNum * 2) <= GSharkMath.Epsilon)
            {
                numberOfArc = 2;
                pts         = new Point3[5];
                ctrPts      = new Point4[5];
                weights     = new double[5];
            }
            else if ((curveAngle - piNum * 3) <= GSharkMath.Epsilon)
            {
                numberOfArc = 3;
                pts         = new Point3[7];
                ctrPts      = new Point4[7];
                weights     = new double[7];
            }
            else
            {
                numberOfArc = 4;
                pts         = new Point3[9];
                ctrPts      = new Point4[9];
                weights     = new double[9];
            }

            double  detTheta = curveAngle / numberOfArc;
            double  weight   = Math.Cos(detTheta / 2);
            Point3  p0       = Center + (axisX * (Radius * Math.Cos(_domain.T0)) + axisY * (Radius * Math.Sin(_domain.T0)));
            Vector3 t0       = axisY * Math.Cos(_domain.T0) - axisX * Math.Sin(_domain.T0);

            KnotVector knots = new KnotVector(CollectionHelpers.RepeatData(0.0, ctrPts.Length + 3));
            int        index = 0;
            double     angle = _domain.T0;

            pts[0]     = p0;
            ctrPts[0]  = new Point4(p0);
            weights[0] = weight;

            for (int i = 1; i < numberOfArc + 1; i++)
            {
                angle += detTheta;
                Point3 p2 = Center + (axisX * (Radius * Math.Cos(angle)) + axisY * (Radius * Math.Sin(angle)));

                ctrPts[index + 2]  = new Point4(p2);
                pts[index + 2]     = p2;
                weights[index + 2] = 1.0;

                Vector3 t2  = (axisY * Math.Cos(angle)) - (axisX * Math.Sin(angle));
                Line    ln0 = new Line(p0, t0.Unitize() + p0);
                Line    ln1 = new Line(p2, t2.Unitize() + p2);
                Intersect.LineLine(ln0, ln1, out _, out _, out double u0, out _);
                Point3 p1 = p0 + (t0 * u0);

                ctrPts[index + 1]  = new Point4(p1, weight);
                pts[index + 1]     = p1;
                weights[index + 1] = weight;
                index += 2;

                if (i >= numberOfArc)
                {
                    continue;
                }

                p0 = p2;
                t0 = t2;
            }

            int j = 2 * numberOfArc + 1;

            for (int i = 0; i < 3; i++)
            {
                knots[i]     = 0.0;
                knots[i + j] = 1.0;
            }

            switch (numberOfArc)
            {
            case 2:
                knots[3] = knots[4] = 0.5;
                break;

            case 3:
                knots[3] = knots[4] = (double)1 / 3;
                knots[5] = knots[6] = (double)2 / 3;
                break;

            case 4:
                knots[3] = knots[4] = 0.25;
                knots[5] = knots[6] = 0.5;
                knots[7] = knots[8] = 0.75;
                break;
            }

            Weights               = weights.ToList();
            Degree                = 2;
            Knots                 = knots;
            ControlPoints         = ctrPts.ToList();
            ControlPointLocations = pts.ToList();
        }
Beispiel #2
0
 public virtual double ClosestParameter(Point3 pt)
 {
     return(Analyze.Curve.ClosestParameter(this, pt));
 }
Beispiel #3
0
        /// <summary>
        ///   Recursively search to find the horizon or lit set.
        /// </summary>
        private void SearchHorizon(List <Point3> points, Point3 point, int prevFaceIndex, int faceCount, Face face)
        {
            Assert(prevFaceIndex >= 0);
            Assert(_litFaces.Contains(prevFaceIndex));
            Assert(!_litFaces.Contains(faceCount));
            Assert(_faces[faceCount].Equals(face));

            _litFaces.Add(faceCount);

            // Use prevFaceIndex to determine what the next face to search will
            // be, and what edges we need to cross to get there. It's important
            // that the search proceeds in counter-clockwise order from the
            // previous face.
            int nextFaceIndex0;
            int nextFaceIndex1;
            int edge0;
            int edge1;
            int edge2;

            if (prevFaceIndex == face.Opposite0)
            {
                nextFaceIndex0 = face.Opposite1;
                nextFaceIndex1 = face.Opposite2;

                edge0 = face.Vertex2;
                edge1 = face.Vertex0;
                edge2 = face.Vertex1;
            }
            else if (prevFaceIndex == face.Opposite1)
            {
                nextFaceIndex0 = face.Opposite2;
                nextFaceIndex1 = face.Opposite0;

                edge0 = face.Vertex0;
                edge1 = face.Vertex1;
                edge2 = face.Vertex2;
            }
            else
            {
                Assert(prevFaceIndex == face.Opposite2);

                nextFaceIndex0 = face.Opposite0;
                nextFaceIndex1 = face.Opposite1;

                edge0 = face.Vertex1;
                edge1 = face.Vertex2;
                edge2 = face.Vertex0;
            }

            if (!_litFaces.Contains(nextFaceIndex0))
            {
                Face oppositeFace = _faces[nextFaceIndex0];

                double dist = PointFaceDistance(
                    point,
                    points[oppositeFace.Vertex0],
                    oppositeFace);

                if (dist <= 0.0f)
                {
                    _horizon.Add(new HorizonEdge
                    {
                        Face  = nextFaceIndex0,
                        Edge0 = edge0,
                        Edge1 = edge1,
                    });
                }
                else
                {
                    SearchHorizon(points, point, faceCount, nextFaceIndex0, oppositeFace);
                }
            }

            if (!_litFaces.Contains(nextFaceIndex1))
            {
                Face oppositeFace = _faces[nextFaceIndex1];

                double dist = PointFaceDistance(
                    point,
                    points[oppositeFace.Vertex0],
                    oppositeFace);

                if (dist <= 0.0f)
                {
                    _horizon.Add(new HorizonEdge
                    {
                        Face  = nextFaceIndex1,
                        Edge0 = edge1,
                        Edge1 = edge2,
                    });
                }
                else
                {
                    SearchHorizon(points, point, faceCount, nextFaceIndex1, oppositeFace);
                }
            }
        }
Beispiel #4
0
        /// <summary>
        ///   Start the search for the horizon.
        ///
        ///   The search is a DFS search that searches neighboring triangles in
        ///   a counter-clockwise fashion. When it find a neighbor which is not
        ///   lit, that edge will be a line on the horizon. If the search always
        ///   proceeds counter-clockwise, the edges of the horizon will be found
        ///   in counter-clockwise order.
        ///
        ///   The heart of the search can be found in the recursive
        ///   SearchHorizon() method, but the the first iteration of the search
        ///   is special, because it has to visit three neighbors (all the
        ///   neighbors of the initial triangle), while the rest of the search
        ///   only has to visit two (because one of them has already been
        ///   visited, the one you came from).
        /// </summary>
        private void FindHorizon(List <Point3> points, Point3 point, int fi, Face face)
        {
            // TODO should I use epsilon in the PointFaceDistance comparisons?

            _litFaces.Clear();
            _horizon.Clear();

            _litFaces.Add(fi);

            Assert(PointFaceDistance(point, points[face.Vertex0], face) > 0.0f);

            // For the rest of the recursive search calls, we first check if the
            // triangle has already been visited and is part of litFaces.
            // However, in this first call we can skip that because we know it
            // can't possibly have been visited yet, since the only thing in
            // litFaces is the current triangle.
            {
                Face oppositeFace = _faces[face.Opposite0];

                double dist = PointFaceDistance(
                    point,
                    points[oppositeFace.Vertex0],
                    oppositeFace);

                if (dist <= 0.0f)
                {
                    _horizon.Add(new HorizonEdge
                    {
                        Face  = face.Opposite0,
                        Edge0 = face.Vertex1,
                        Edge1 = face.Vertex2,
                    });
                }
                else
                {
                    SearchHorizon(points, point, fi, face.Opposite0, oppositeFace);
                }
            }

            if (!_litFaces.Contains(face.Opposite1))
            {
                Face oppositeFace = _faces[face.Opposite1];

                double dist = PointFaceDistance(
                    point,
                    points[oppositeFace.Vertex0],
                    oppositeFace);

                if (dist <= 0.0f)
                {
                    _horizon.Add(new HorizonEdge
                    {
                        Face  = face.Opposite1,
                        Edge0 = face.Vertex2,
                        Edge1 = face.Vertex0,
                    });
                }
                else
                {
                    SearchHorizon(points, point, fi, face.Opposite1, oppositeFace);
                }
            }

            if (!_litFaces.Contains(face.Opposite2))
            {
                Face oppositeFace = _faces[face.Opposite2];

                double dist = PointFaceDistance(
                    point,
                    points[oppositeFace.Vertex0],
                    oppositeFace);

                if (dist <= 0.0f)
                {
                    _horizon.Add(new HorizonEdge
                    {
                        Face  = face.Opposite2,
                        Edge0 = face.Vertex0,
                        Edge1 = face.Vertex1,
                    });
                }
                else
                {
                    SearchHorizon(points, point, fi, face.Opposite2, oppositeFace);
                }
            }
        }
Beispiel #5
0
 private Vector3 Normal(Point3 v0, Point3 v1, Point3 v2)
 {
     return(Vector3.CrossProduct(v1 - v0, v2 - v0).Unitize());
 }
Beispiel #6
0
 private double PointFaceDistance(Point3 point, Point3 pointOnFace, Face face)
 {
     return(Vector3.DotProduct(face.Normal, point - pointOnFace));
 }