示例#1
0
        /**
         * Returns how many times ray from point (x,y) cross cubic curve
         */
        public static int crossCubic(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2, double x, double y)
        {
            // LEFT/RIGHT/UP/EMPTY
            if ((x < x1 && x < cx1 && x < cx2 && x < x2) ||
                (x > x1 && x > cx1 && x > cx2 && x > x2) ||
                (y > y1 && y > cy1 && y > cy2 && y > y2) ||
                (x1 == cx1 && cx1 == cx2 && cx2 == x2))
            {
                return 0;
            }

            // DOWN
            if (y < y1 && y < cy1 && y < cy2 && y < y2 && x != x1 && x != x2)
            {
                if (x1 < x2)
                {
                    return x1 < x && x < x2 ? 1 : 0;
                }
                return x2 < x && x < x1 ? -1 : 0;
            }

            // INSIDE
            CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2);
            double px = x - x1;
            double py = y - y1;
            double[] res = new double[3];
            int rc = c.solvePoint(res, px);
            return c.cross(res, rc, py, py);
        }
示例#2
0
        public void DeferredUpdate()
        {
            lock (this)
            {
                if (!_dirty)
                {
                    return;
                }
                _dirty = false;
            }

            FromMatrix = MatrixD.CreateWorld(From.Position, CorrectTangent(From.Tangent), From.Up);
            ToMatrix   = MatrixD.CreateWorld(To.Position, CorrectTangent(To.Tangent), To.Up);


            var ext = Math.Max((FromMatrix.Translation - ToMatrix.Translation).Length() / 3, 1f);
            var d1  = default(Vector3D);
            var d2  = default(Vector3D);

            if (Mode != CurveMode.Linear)
            {
                if (_ctl0.HasValue)
                {
                    d1 = Vector3D.Transform(_ctl0.Value, FromMatrix);
                }
                else
                {
                    d1 = FromMatrix.Translation + (FromMatrix.Forward * ext);
                }
                if (_ctl1.HasValue)
                {
                    d2 = Vector3D.Transform(_ctl1.Value, ToMatrix);
                }
                else
                {
                    d2 = ToMatrix.Translation - (ToMatrix.Forward * ext);
                }
            }


            switch (Mode)
            {
            case CurveMode.Linear:
                Curve = new LinearCurve(From.Position, To.Position);
                break;

            case CurveMode.QuadraticBez:
                Curve = new QuadraticCurve(FromMatrix.Translation, (d1 + d2) / 2, ToMatrix.Translation);
                break;

            case CurveMode.CubicBez:
                Curve = new CubicCurve(FromMatrix.Translation, d1, d2, ToMatrix.Translation);
                break;

            default:
                throw new Exception($"Unsupported curve mode {Mode}");
            }

            CurveUpdated?.Invoke(this);
        }
示例#3
0
        /**
         * Returns how many times ray from point (x,y) cross cubic curve
         */
        public static int crossCubic(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2, double x, double y)
        {
            // LEFT/RIGHT/UP/EMPTY
            if ((x < x1 && x < cx1 && x < cx2 && x < x2) ||
                (x > x1 && x > cx1 && x > cx2 && x > x2) ||
                (y > y1 && y > cy1 && y > cy2 && y > y2) ||
                (x1 == cx1 && cx1 == cx2 && cx2 == x2))
            {
                return(0);
            }

            // DOWN
            if (y < y1 && y < cy1 && y < cy2 && y < y2 && x != x1 && x != x2)
            {
                if (x1 < x2)
                {
                    return(x1 < x && x < x2 ? 1 : 0);
                }
                return(x2 < x && x < x1 ? -1 : 0);
            }

            // INSIDE
            CubicCurve c  = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2);
            double     px = x - x1;
            double     py = y - y1;

            double[] res = new double[3];
            int      rc  = c.solvePoint(res, px);

            return(c.cross(res, rc, py, py));
        }
示例#4
0
        private void GenerateMap()
        {
            PerlinNoise perlin   = new PerlinNoise();
            var         contrast = new CubicCurve();

            images = new Texture2D[map_width][];
            for (int x = 0; x < map_width; x++)
            {
                images[x] = new Texture2D[map_height];
                for (int y = 0; y < map_height; y++)
                {
                    var n = perlin.GetPoint(x * 0.1, y * 0.1);
                    n            = CubicCurve.Contrast(n);
                    images[x][y] = ChooseTile(n);
                }
            }
        }
示例#5
0
        ////////////////////////////////////////////////////////////////////////////
        //--------------------------------- REVISIONS ------------------------------
        // Date       Name                 Tracking #         Description
        // ---------  -------------------  -------------      ----------------------
        // 13JUN2009  James Shen                              Initial Creation
        ////////////////////////////////////////////////////////////////////////////
        private void Next(bool doNext)
        {
            int level;

            if (_holdIndex >= _holdEnd)
            {
                if (doNext)
                {
                    _src.Next();
                }
                if (_src.IsDone())
                {
                    _done = true;
                    return;
                }
                _holdType = _src.CurrentSegment(_intHold);
                for (int i = 0; i < _intHold.Length; i++)
                {
                    _hold[i] = _intHold[i];
                }
                _levelIndex = 0;
                _levels[0]  = 0;
            }

            switch (_holdType)
            {
            case SEG_MOVETO:
            case SEG_LINETO:
                _curx = _hold[0];
                _cury = _hold[1];
                if (_holdType == SEG_MOVETO)
                {
                    _movx = _curx;
                    _movy = _cury;
                }
                _holdIndex = 0;
                _holdEnd   = 0;
                break;

            case SEG_CLOSE:
                _curx      = _movx;
                _cury      = _movy;
                _holdIndex = 0;
                _holdEnd   = 0;
                break;

            case SEG_QUADTO:
                if (_holdIndex >= _holdEnd)
                {
                    // Move the coordinates to the end of the array.
                    _holdIndex            = _hold.Length - 6;
                    _holdEnd              = _hold.Length - 2;
                    _hold[_holdIndex + 0] = _curx;
                    _hold[_holdIndex + 1] = _cury;
                    _hold[_holdIndex + 2] = _hold[0];
                    _hold[_holdIndex + 3] = _hold[1];
                    _hold[_holdIndex + 4] = _curx = _hold[2];
                    _hold[_holdIndex + 5] = _cury = _hold[3];
                }

                level = _levels[_levelIndex];
                while (level < _limit)
                {
                    for (int i = 0; i < _intHold.Length; i++)
                    {
                        _intHold[i] = (int)(_hold[i] + .5);
                    }
                    if (QuadCurve.GetFlatnessSq(_intHold, _holdIndex) < _squareflat)
                    {
                        break;
                    }

                    EnsureHoldCapacity(4);
                    QuadCurve.Subdivide(_hold, _holdIndex,
                                        _hold, _holdIndex - 4,
                                        _hold, _holdIndex);
                    _holdIndex -= 4;

                    // Now that we have subdivided, we have constructed
                    // two curves of one depth lower than the original
                    // curve.  One of those curves is in the place of
                    // the former curve and one of them is in the next
                    // set of held coordinate slots.  We now set both
                    // curves level values to the next higher level.
                    level++;
                    _levels[_levelIndex] = level;
                    _levelIndex++;
                    _levels[_levelIndex] = level;
                }

                // This curve segment is flat enough, or it is too deep
                // in recursion levels to try to flatten any more.  The
                // two coordinates at holdIndex+4 and holdIndex+5 now
                // contain the endpoint of the curve which can be the
                // endpoint of an approximating line segment.
                _holdIndex += 4;
                _levelIndex--;
                break;

            case SEG_CUBICTO:
                if (_holdIndex >= _holdEnd)
                {
                    // Move the coordinates to the end of the array.
                    _holdIndex            = _hold.Length - 8;
                    _holdEnd              = _hold.Length - 2;
                    _hold[_holdIndex + 0] = _curx;
                    _hold[_holdIndex + 1] = _cury;
                    _hold[_holdIndex + 2] = _hold[0];
                    _hold[_holdIndex + 3] = _hold[1];
                    _hold[_holdIndex + 4] = _hold[2];
                    _hold[_holdIndex + 5] = _hold[3];
                    _hold[_holdIndex + 6] = _curx = _hold[4];
                    _hold[_holdIndex + 7] = _cury = _hold[5];
                }

                level = _levels[_levelIndex];
                while (level < _limit)
                {
                    for (int i = 0; i < _intHold.Length; i++)
                    {
                        _intHold[i] = (int)(_hold[i] + .5);
                    }
                    if (CubicCurve.GetFlatnessSq(_intHold, _holdIndex) < _squareflat)
                    {
                        break;
                    }

                    EnsureHoldCapacity(6);
                    CubicCurve.Subdivide(_hold, _holdIndex,
                                         _hold, _holdIndex - 6,
                                         _hold, _holdIndex);
                    _holdIndex -= 6;

                    // Now that we have subdivided, we have constructed
                    // two curves of one depth lower than the original
                    // curve.  One of those curves is in the place of
                    // the former curve and one of them is in the next
                    // set of held coordinate slots.  We now set both
                    // curves level values to the next higher level.
                    level++;
                    _levels[_levelIndex] = level;
                    _levelIndex++;
                    _levels[_levelIndex] = level;
                }

                // This curve segment is flat enough, or it is too deep
                // in recursion levels to try to flatten any more.  The
                // two coordinates at holdIndex+6 and holdIndex+7 now
                // contain the endpoint of the curve which can be the
                // endpoint of an approximating line segment.
                _holdIndex += 6;
                _levelIndex--;
                break;
            }
        }
示例#6
0
 internal CubicIterator(CubicCurve q, AffineTransform at)
 {
     _cubic  = q;
     _affine = at;
 }
示例#7
0
        /**
         * Returns how many times rectangle stripe cross cubic curve or the are intersect
         */
        public static int intersectCubic(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2, double rx1, double ry1, double rx2, double ry2)
        {
            // LEFT/RIGHT/UP
            if ((rx2 < x1 && rx2 < cx1 && rx2 < cx2 && rx2 < x2) ||
                (rx1 > x1 && rx1 > cx1 && rx1 > cx2 && rx1 > x2) ||
                (ry1 > y1 && ry1 > cy1 && ry1 > cy2 && ry1 > y2))
            {
                return 0;
            }

            // DOWN
            if (ry2 < y1 && ry2 < cy1 && ry2 < cy2 && ry2 < y2 && rx1 != x1 && rx1 != x2)
            {
                if (x1 < x2)
                {
                    return x1 < rx1 && rx1 < x2 ? 1 : 0;
                }
                return x2 < rx1 && rx1 < x1 ? -1 : 0;
            }

            // INSIDE
            CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2);
            double px1 = rx1 - x1;
            double py1 = ry1 - y1;
            double px2 = rx2 - x1;
            double py2 = ry2 - y1;

            double[] res1 = new double[3];
            double[] res2 = new double[3];
            int rc1 = c.solvePoint(res1, px1);
            int rc2 = c.solvePoint(res2, px2);

            // LEFT/RIGHT
            if (rc1 == 0 && rc2 == 0)
            {
                return 0;
            }

            double minX = px1 - DELTA;
            double maxX = px2 + DELTA;

            // Build bound --------------------------------------------------------
            double[] bound = new double[40];
            int bc = 0;
            // Add roots
            bc = c.addBound(bound, bc, res1, rc1, minX, maxX, false, 0);
            bc = c.addBound(bound, bc, res2, rc2, minX, maxX, false, 1);
            // Add extrimal points
            rc2 = c.solveExtremX(res2);
            bc = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 2);
            rc2 = c.solveExtremY(res2);
            bc = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 4);
            // Add start and end
            if (rx1 < x1 && x1 < rx2)
            {
                bound[bc++] = 0.0;
                bound[bc++] = 0.0;
                bound[bc++] = 0.0;
                bound[bc++] = 6;
            }
            if (rx1 < x2 && x2 < rx2)
            {
                bound[bc++] = 1.0;
                bound[bc++] = c.ax;
                bound[bc++] = c.ay;
                bound[bc++] = 7;
            }
            // End build bound ----------------------------------------------------

            int cross = crossBound(bound, bc, py1, py2);
            if (cross != UNKNOWN)
            {
                return cross;
            }
            return c.cross(res1, rc1, py1, py2);
        }
示例#8
0
 internal CubicIterator(CubicCurve q, AffineTransform at)
 {
     _cubic = q;
     _affine = at;
 }
示例#9
0
        /**
         * Returns how many times rectangle stripe cross cubic curve or the are intersect
         */
        public static int intersectCubic(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2, double rx1, double ry1, double rx2, double ry2)
        {
            // LEFT/RIGHT/UP
            if ((rx2 < x1 && rx2 < cx1 && rx2 < cx2 && rx2 < x2) ||
                (rx1 > x1 && rx1 > cx1 && rx1 > cx2 && rx1 > x2) ||
                (ry1 > y1 && ry1 > cy1 && ry1 > cy2 && ry1 > y2))
            {
                return(0);
            }

            // DOWN
            if (ry2 < y1 && ry2 < cy1 && ry2 < cy2 && ry2 < y2 && rx1 != x1 && rx1 != x2)
            {
                if (x1 < x2)
                {
                    return(x1 < rx1 && rx1 < x2 ? 1 : 0);
                }
                return(x2 < rx1 && rx1 < x1 ? -1 : 0);
            }

            // INSIDE
            CubicCurve c   = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2);
            double     px1 = rx1 - x1;
            double     py1 = ry1 - y1;
            double     px2 = rx2 - x1;
            double     py2 = ry2 - y1;

            double[] res1 = new double[3];
            double[] res2 = new double[3];
            int      rc1  = c.solvePoint(res1, px1);
            int      rc2  = c.solvePoint(res2, px2);

            // LEFT/RIGHT
            if (rc1 == 0 && rc2 == 0)
            {
                return(0);
            }

            double minX = px1 - DELTA;
            double maxX = px2 + DELTA;

            // Build bound --------------------------------------------------------
            double[] bound = new double[40];
            int      bc    = 0;

            // Add roots
            bc = c.addBound(bound, bc, res1, rc1, minX, maxX, false, 0);
            bc = c.addBound(bound, bc, res2, rc2, minX, maxX, false, 1);
            // Add extrimal points
            rc2 = c.solveExtremX(res2);
            bc  = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 2);
            rc2 = c.solveExtremY(res2);
            bc  = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 4);
            // Add start and end
            if (rx1 < x1 && x1 < rx2)
            {
                bound[bc++] = 0.0;
                bound[bc++] = 0.0;
                bound[bc++] = 0.0;
                bound[bc++] = 6;
            }
            if (rx1 < x2 && x2 < rx2)
            {
                bound[bc++] = 1.0;
                bound[bc++] = c.ax;
                bound[bc++] = c.ay;
                bound[bc++] = 7;
            }
            // End build bound ----------------------------------------------------

            int cross = crossBound(bound, bc, py1, py2);

            if (cross != UNKNOWN)
            {
                return(cross);
            }
            return(c.cross(res1, rc1, py1, py2));
        }