예제 #1
0
 public bool Equals(DoublePoint other)
 {
     return
         (Math.Abs(X - other.X) < GeometryHelper.Tolerance &&
          Math.Abs(Y - other.Y) < GeometryHelper.Tolerance);
 }
예제 #2
0
        private void DoOffset(double delta)
        {
            _destinationPolygons = new PolygonPath();
            _delta = delta;

            //if Zero offset, just copy any CLOSED polygons to m_p and return ...
            if (GeometryHelper.NearZero(delta))
            {
                _destinationPolygons.Capacity = _polygonNodes.Children.Count;
                foreach (var node in _polygonNodes.Children)
                {
                    if (node.EndType == EndType.ClosedPolygon)
                    {
                        _destinationPolygons.Add(node.Polygon);
                    }
                }
                return;
            }

            // see offset_triginometry3.svg in the documentation folder ...
            if (MiterLimit > 2)
            {
                _miterLim = 2 / (MiterLimit * MiterLimit);
            }
            else
            {
                _miterLim = 0.5;
            }

            double y;

            if (ArcTolerance <= 0.0)
            {
                y = DefaultArcTolerance;
            }
            else if (ArcTolerance > Math.Abs(delta) * DefaultArcTolerance)
            {
                y = Math.Abs(delta) * DefaultArcTolerance;
            }
            else
            {
                y = ArcTolerance;
            }

            // see offset_triginometry2.svg in the documentation folder ...
            var steps = Math.PI / Math.Acos(1 - y / Math.Abs(delta));

            _sin         = Math.Sin(TwpPi / steps);
            _cos         = Math.Cos(TwpPi / steps);
            _stepsPerRad = steps / TwpPi;
            if (delta < 0.0)
            {
                _sin = -_sin;
            }

            _destinationPolygons.Capacity = _polygonNodes.Children.Count * 2;

            foreach (var node in _polygonNodes.Children)
            {
                _sourcePolygon = node.Polygon;

                var len = _sourcePolygon.Count;

                if (len == 0 ||
                    delta <= 0 &&
                    (len < 3 || node.EndType != EndType.ClosedPolygon))
                {
                    continue;
                }

                _destinationPolygon = new Polygon();

                if (len == 1)
                {
                    if (node.JoinType == JoinType.Round)
                    {
                        var x = 1.0;
                        var Y = 0.0;
                        for (var j = 1; j <= steps; j++)
                        {
                            _destinationPolygon.Add(new IntPoint(
                                                        (_sourcePolygon[0].X + x * delta).RoundToLong(),
                                                        (_sourcePolygon[0].Y + Y * delta).RoundToLong()));
                            var x2 = x;
                            x = x * _cos - _sin * Y;
                            Y = x2 * _sin + Y * _cos;
                        }
                    }
                    else
                    {
                        var x = -1.0;
                        var Y = -1.0;

                        for (var j = 0; j < 4; ++j)
                        {
                            _destinationPolygon.Add(new IntPoint(
                                                        (_sourcePolygon[0].X + x * delta).RoundToLong(),
                                                        (_sourcePolygon[0].Y + Y * delta).RoundToLong()));

                            if (x < 0)
                            {
                                x = 1;
                            }
                            else if (Y < 0)
                            {
                                Y = 1;
                            }
                            else
                            {
                                x = -1;
                            }
                        }
                    }
                    _destinationPolygons.Add(_destinationPolygon);
                    continue;
                }

                //build _normals ...
                _normals.Clear();
                _normals.Capacity = len;
                for (int j = 0; j < len - 1; j++)
                {
                    _normals.Add(GetUnitNormal(_sourcePolygon[j], _sourcePolygon[j + 1]));
                }
                if (node.EndType == EndType.ClosedLine ||
                    node.EndType == EndType.ClosedPolygon)
                {
                    _normals.Add(GetUnitNormal(_sourcePolygon[len - 1], _sourcePolygon[0]));
                }
                else
                {
                    _normals.Add(new DoublePoint(_normals[len - 2]));
                }

                if (node.EndType == EndType.ClosedPolygon)
                {
                    int k = len - 1;
                    for (int j = 0; j < len; j++)
                    {
                        OffsetPoint(j, ref k, node.JoinType);
                    }
                    _destinationPolygons.Add(_destinationPolygon);
                }
                else if (node.EndType == EndType.ClosedLine)
                {
                    int k = len - 1;
                    for (int j = 0; j < len; j++)
                    {
                        OffsetPoint(j, ref k, node.JoinType);
                    }
                    _destinationPolygons.Add(_destinationPolygon);
                    _destinationPolygon = new Polygon();
                    //re-build _normals ...
                    DoublePoint n = _normals[len - 1];
                    for (int j = len - 1; j > 0; j--)
                    {
                        _normals[j] = new DoublePoint(-_normals[j - 1].X, -_normals[j - 1].Y);
                    }
                    _normals[0] = new DoublePoint(-n.X, -n.Y);
                    k           = 0;
                    for (int j = len - 1; j >= 0; j--)
                    {
                        OffsetPoint(j, ref k, node.JoinType);
                    }
                    _destinationPolygons.Add(_destinationPolygon);
                }
                else
                {
                    var k = 0;
                    for (var j = 1; j < len - 1; ++j)
                    {
                        OffsetPoint(j, ref k, node.JoinType);
                    }

                    IntPoint pt1;
                    if (node.EndType == EndType.OpenButt)
                    {
                        var j = len - 1;
                        pt1 = new IntPoint(
                            (_sourcePolygon[j].X + _normals[j].X * delta).RoundToLong(),
                            (_sourcePolygon[j].Y + _normals[j].Y * delta).RoundToLong());

                        _destinationPolygon.Add(pt1);

                        pt1 = new IntPoint(
                            (_sourcePolygon[j].X - _normals[j].X * delta).RoundToLong(),
                            (_sourcePolygon[j].Y - _normals[j].Y * delta).RoundToLong());

                        _destinationPolygon.Add(pt1);
                    }
                    else
                    {
                        var j = len - 1;
                        k           = len - 2;
                        _sinA       = 0;
                        _normals[j] = new DoublePoint(-_normals[j].X, -_normals[j].Y);
                        if (node.EndType == EndType.OpenSquare)
                        {
                            DoSquare(j, k);
                        }
                        else
                        {
                            DoRound(j, k);
                        }
                    }

                    //re-build _normals ...
                    for (int j = len - 1; j > 0; j--)
                    {
                        _normals[j] = new DoublePoint(-_normals[j - 1].X, -_normals[j - 1].Y);
                    }

                    _normals[0] = new DoublePoint(-_normals[1].X, -_normals[1].Y);

                    k = len - 1;
                    for (int j = k - 1; j > 0; --j)
                    {
                        OffsetPoint(j, ref k, node.JoinType);
                    }

                    if (node.EndType == EndType.OpenButt)
                    {
                        pt1 = new IntPoint(
                            (_sourcePolygon[0].X - _normals[0].X * delta).RoundToLong(),
                            (_sourcePolygon[0].Y - _normals[0].Y * delta).RoundToLong());

                        _destinationPolygon.Add(pt1);

                        pt1 = new IntPoint(
                            (_sourcePolygon[0].X + _normals[0].X * delta).RoundToLong(),
                            (_sourcePolygon[0].Y + _normals[0].Y * delta).RoundToLong());

                        _destinationPolygon.Add(pt1);
                    }
                    else
                    {
                        _sinA = 0;
                        if (node.EndType == EndType.OpenSquare)
                        {
                            DoSquare(0, 1);
                        }
                        else
                        {
                            DoRound(0, 1);
                        }
                    }
                    _destinationPolygons.Add(_destinationPolygon);
                }
            }
        }
예제 #3
0
 public DoublePoint(DoublePoint point)
 {
     X = point.X;
     Y = point.Y;
 }