Пример #1
0
        /// <summary>
        /// Creates an AffineTransformation defined by a mapping between two baselines.
        /// The computed transformation consists of:
        /// <list type="bullet">
        /// <item><description>a translation from the start point of the source baseline to the start point of the destination baseline,</description></item>
        /// <item><description>a rotation through the angle between the baselines about the destination start point,</description></item>
        /// <item><description>and a scaling equal to the ratio of the baseline lengths.</description></item>
        /// </list>
        /// If the source baseline has zero length, an identity transformation is returned.
        /// </summary>
        /// <param name="src0">The start point of the source baseline</param>
        /// <param name="src1">The end point of the source baseline</param>
        /// <param name="dest0">The start point of the destination baseline</param>
        /// <param name="dest1">The end point of the destination baseline</param>
        /// <returns></returns>
        public static AffineTransformation CreateFromBaseLines(
            Coordinate src0, Coordinate src1,
            Coordinate dest0, Coordinate dest1)
        {
            var rotPt = new Coordinate(src0.X + dest1.X - dest0.X, src0.Y + dest1.Y - dest0.Y);

            double ang = AngleUtility.AngleBetweenOriented(src1, src0, rotPt);

            double srcDist  = src1.Distance(src0);
            double destDist = dest1.Distance(dest0);

            // return identity if transformation would be degenerate
            if (srcDist == 0.0)
            {
                return(new AffineTransformation());
            }

            double scale = destDist / srcDist;

            var trans = AffineTransformation.TranslationInstance(
                -src0.X, -src0.Y);

            trans.Rotate(ang);
            trans.Scale(scale, scale);
            trans.Translate(dest0.X, dest0.Y);
            return(trans);
        }
Пример #2
0
        /// <summary>
        /// Creates an AffineTransformation defined by a pair of control vectors. A
        /// control vector consists of a source point and a destination point, which is
        /// the image of the source point under the desired transformation. The
        /// computed transformation is a combination of one or more of a uniform scale,
        /// a rotation, and a translation (i.e. there is no shear component and no
        /// reflection)
        /// </summary>
        /// <param name="src0"></param>
        /// <param name="src1"></param>
        /// <param name="dest0"></param>
        /// <param name="dest1"></param>
        /// <returns>The computed transformation</returns>
        /// <returns><c>null</c> if the control vectors do not determine a well-defined transformation</returns>
        public static AffineTransformation CreateFromControlVectors(Coordinate src0,
                                                                    Coordinate src1, Coordinate dest0, Coordinate dest1)
        {
            var rotPt = new Coordinate(dest1.X - dest0.X, dest1.Y - dest0.Y);

            double ang = AngleUtility.AngleBetweenOriented(src1, src0, rotPt);

            double srcDist  = src1.Distance(src0);
            double destDist = dest1.Distance(dest0);

            if (srcDist == 0.0)
            {
                return(null);
            }

            double scale = destDist / srcDist;

            var trans = AffineTransformation.TranslationInstance(
                -src0.X, -src0.Y);

            trans.Rotate(ang);
            trans.Scale(scale, scale);
            trans.Translate(dest0.X, dest0.Y);
            return(trans);
        }
Пример #3
0
        ///<summary>
        /// Adds a limited mitre join connecting the two reflex offset segments.
        ///</summary>
        /// <remarks>
        /// A limited mitre is a mitre which is beveled at the distance
        /// determined by the mitre ratio limit.
        /// </remarks>
        /// <param name="offset0">The first offset segment</param>
        /// <param name="offset1">The second offset segment</param>
        /// <param name="distance">The offset distance</param>
        /// <param name="mitreLimit">The mitre limit ratio</param>
        private void AddLimitedMitreJoin(
            LineSegment offset0,
            LineSegment offset1,
            double distance,
            double mitreLimit)
        {
            Coordinate basePt = _seg0.P1;

            double ang0 = AngleUtility.Angle(basePt, _seg0.P0);
            double ang1 = AngleUtility.Angle(basePt, _seg1.P1);

            // oriented angle between segments
            double angDiff = AngleUtility.AngleBetweenOriented(_seg0.P0, basePt, _seg1.P1);
            // half of the interior angle
            double angDiffHalf = angDiff / 2;

            // angle for bisector of the interior angle between the segments
            double midAng = AngleUtility.Normalize(ang0 + angDiffHalf);
            // rotating this by PI gives the bisector of the reflex angle
            double mitreMidAng = AngleUtility.Normalize(midAng + Math.PI);

            // the miterLimit determines the distance to the mitre bevel
            double mitreDist = mitreLimit * distance;
            // the bevel delta is the difference between the buffer distance
            // and half of the length of the bevel segment
            double bevelDelta   = mitreDist * Math.Abs(Math.Sin(angDiffHalf));
            double bevelHalfLen = distance - bevelDelta;

            // compute the midpoint of the bevel segment
            double     bevelMidX  = basePt.X + mitreDist * Math.Cos(mitreMidAng);
            double     bevelMidY  = basePt.Y + mitreDist * Math.Sin(mitreMidAng);
            Coordinate bevelMidPt = new Coordinate(bevelMidX, bevelMidY);

            // compute the mitre midline segment from the corner point to the bevel segment midpoint
            LineSegment mitreMidLine = new LineSegment(basePt, bevelMidPt);

            // finally the bevel segment endpoints are computed as offsets from
            // the mitre midline
            Coordinate bevelEndLeft  = mitreMidLine.PointAlongOffset(1.0, bevelHalfLen);
            Coordinate bevelEndRight = mitreMidLine.PointAlongOffset(1.0, -bevelHalfLen);

            if (_side == Positions.Left)
            {
                _vertexList.AddPt(bevelEndLeft);
                _vertexList.AddPt(bevelEndRight);
            }
            else
            {
                _vertexList.AddPt(bevelEndRight);
                _vertexList.AddPt(bevelEndLeft);
            }
        }