Ejemplo n.º 1
0
        /// <summary>
        /// Defines links for this face. A prior call to <c>SetLine</c> is required.
        /// </summary>
        /// <param name="prev">The preceding face (after it has been processed via a call to
        /// <c>SetLine</c>, Must refer to the same polygon as this face.</param>
        /// <returns>The links (the number of array elements will equal the value that came
        /// back from the <c>SetLine</c> call)</returns>
        internal PolygonLink[] CreateLinks(PolygonFace prev)
        {
            Debug.Assert(m_Polygon!=null);
            Debug.Assert(m_Divider!=null);
            Debug.Assert(prev.Divider!=null);
            Debug.Assert(Object.ReferenceEquals(prev.Polygon, m_Polygon));

            // Try to obtain a point feature at the beginning of this face.
            ISpatialIndex index = CadastralMapModel.Current.Index;
            PointFeature beginPoint = new FindPointQuery(index, m_Begin).Result;

            // If the polygon to the left of the this face? (if so, curve-related
            // things may need to be reversed below)
            bool isPolLeft = (m_Divider.Left == m_Polygon);

            // Default geometric info we need to define
            bool isCurveEnd = false;
            bool isRadial = false;
            double bearing = 0.0;
            double angle = 0.0;

            // Is the position at the beginning of this face the start
            // or end of a circular arc (points between 2 curves (on
            // compound curve) are NOT considered to be curve ends). Note
            // that the line could either be a CircularArc, or a topological
            // section based on a circular arc.

            ICircularArcGeometry prevArc = (prev.Divider.LineGeometry as ICircularArcGeometry);
            ICircularArcGeometry thisArc = (m_Divider.LineGeometry as ICircularArcGeometry);
            bool isPrevCurve = (prevArc!=null);
            bool isThisCurve = (thisArc!=null);
            isCurveEnd = (isPrevCurve!=isThisCurve);

            // If we are dealing with a point between two curves try to
            // set the curve parameters and, if successful, we will treat
            // the point as a radial point.

            if (isPrevCurve && isThisCurve)
            {
                isRadial = true;

                // Get the curve parameters...

                IPosition prevcen = prevArc.Circle.Center;
                double prevrad = prevArc.Circle.Radius;

                IPosition thiscen = thisArc.Circle.Center;
                double thisrad = thisArc.Circle.Radius;

                // We only need to know the sense for one of the arcs
                bool iscw = thisArc.IsClockwise;

                // If the 2 curves do not have the same centre and radius,
                // see if they are really close (to the nearest centimeter
                // on the ground). In that case, use the average values for
                // the 2 curves. If they really are different curves, don't
                // treat this as a radial curve point -- treat it as a
                // curve end instead.

                IPosition centre = null;	    // The centre to actually use

                if (!(prevcen==thiscen && Math.Abs(prevrad-thisrad)<Constants.TINY))
                {
                    double xc1 = prevcen.X;
                    double yc1 = prevcen.Y;
                    double xc2 = thiscen.X;
                    double yc2 = thiscen.Y;
                    double dxc = xc2-xc1;
                    double dyc = yc2-yc1;

                    if (Math.Abs(dxc)<0.01 &&
                        Math.Abs(dyc)<0.01 &&
                        Math.Abs(prevrad-thisrad)<0.01)
                    {
                        // Close enough
                        centre = new Position(xc1+dxc*0.5, yc1+dyc*0.5);
                    }
                    else
                    {
                        isRadial = false;
                        isCurveEnd = true;
                    }
                }
                else
                    centre = prevcen;

                // If the centre and radius were the same (or close enough),
                // define the radial bearing from the centre of the circle.
                // If the polygon is actually on the other side, reverse the
                // bearing so that it's directed INTO the polygon.

                if (isRadial)
                {
                    Debug.Assert(centre!=null);
                    bearing = Geom.BearingInRadians(centre, m_Begin);
                    angle = 0.0;
                    if (iscw  != isPolLeft)
                        bearing += Constants.PI;
                }
            }

            // If we're not dealing with a radial curve (or we have curves that
            // don't appear to be radial)
            if (!isRadial)
            {
                // Get the clockwise angle from the last position of the
                // preceding face to the first position after the start
                // of this face. Since info is held in a clockwise cycle
                // around the polygon, this will always give us the exterior
                // angle.
                Turn reference = new Turn(m_Begin, prev.TailReference);
                angle = reference.GetAngleInRadians(this.HeadReference);

                // Define the bearing to use for projecting the point. It's
                // in the middle of the angle, but projected into the polygon.
                bearing = reference.BearingInRadians + angle*0.5 + Constants.PI;
            }

            // Initialize the link at the start of the face
            List<PolygonLink> links = new List<PolygonLink>();
            PolygonLink link = new PolygonLink(beginPoint, isCurveEnd, isRadial, bearing, angle);
            links.Add(link);

            // Initialize links for any extra points
            if (m_ExtraPoints!=null)
            {
                // Intermediate points can never be curve ends
                isCurveEnd = false;

                // If the face is a curve, they're radial points
                isRadial = isThisCurve;

                // Note any curve info
                double radius;
                IPosition centre = null;
                bool iscw = false;

                if (isRadial)
                {
                    Debug.Assert(m_Divider.Line.LineGeometry is ICircularArcGeometry);
                    ICircularArcGeometry arc = (m_Divider.Line.LineGeometry as ICircularArcGeometry);
                    centre = arc.Circle.Center;
                    radius = arc.Circle.Radius;
                    iscw = arc.IsClockwise;
                    angle = 0.0;
                }

                for (uint i=0; i<m_ExtraPoints.Length; i++)
                {
                    //IPointGeometry loc = m_ExtraPoints[i].Geometry;
                    PointFeature loc = m_ExtraPoints[i];

                    // Figure out the orientation bearing for the point
                    if (isRadial)
                    {
                        Debug.Assert(centre!=null);
                        bearing = Geom.BearingInRadians(centre, loc);
                        if (iscw  != isPolLeft)
                            bearing += Constants.PI;
                    }
                    else
                    {
                        // Get the exterior clockwise angle

                        IPointGeometry back;
                        IPointGeometry fore;

                        if (i==0)
                            back = m_Begin;
                        else
                            back = m_ExtraPoints[i-1].Geometry;

                        if (i==(m_ExtraPoints.Length-1))
                            fore = m_End;
                        else
                            fore = m_ExtraPoints[i+1].Geometry;

                        Turn reference = new Turn(loc, back);
                        angle = reference.GetAngleInRadians(fore);

                        // Define the bearing to use for projecting the point. It's
                        // in the middle of the angle, but projected into the polygon.
                        bearing = reference.BearingInRadians + angle*0.5 + Constants.PI;
                    }

                    link = new PolygonLink(m_ExtraPoints[i], isCurveEnd, isRadial, bearing, angle);
                    links.Add(link);
                }
            }

            return links.ToArray();
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Defines links for this face. A prior call to <c>SetLine</c> is required.
        /// </summary>
        /// <param name="prev">The preceding face (after it has been processed via a call to
        /// <c>SetLine</c>, Must refer to the same polygon as this face.</param>
        /// <returns>The links (the number of array elements will equal the value that came
        /// back from the <c>SetLine</c> call)</returns>
        internal PolygonLink[] CreateLinks(PolygonFace prev)
        {
            Debug.Assert(m_Polygon != null);
            Debug.Assert(m_Divider != null);
            Debug.Assert(prev.Divider != null);
            Debug.Assert(Object.ReferenceEquals(prev.Polygon, m_Polygon));

            // Try to obtain a point feature at the beginning of this face.
            ISpatialIndex index      = CadastralMapModel.Current.Index;
            PointFeature  beginPoint = new FindPointQuery(index, m_Begin).Result;

            // If the polygon to the left of the this face? (if so, curve-related
            // things may need to be reversed below)
            bool isPolLeft = (m_Divider.Left == m_Polygon);

            // Default geometric info we need to define
            bool   isCurveEnd = false;
            bool   isRadial   = false;
            double bearing    = 0.0;
            double angle      = 0.0;

            // Is the position at the beginning of this face the start
            // or end of a circular arc (points between 2 curves (on
            // compound curve) are NOT considered to be curve ends). Note
            // that the line could either be a CircularArc, or a topological
            // section based on a circular arc.

            ICircularArcGeometry prevArc = (prev.Divider.LineGeometry as ICircularArcGeometry);
            ICircularArcGeometry thisArc = (m_Divider.LineGeometry as ICircularArcGeometry);
            bool isPrevCurve             = (prevArc != null);
            bool isThisCurve             = (thisArc != null);

            isCurveEnd = (isPrevCurve != isThisCurve);

            // If we are dealing with a point between two curves try to
            // set the curve parameters and, if successful, we will treat
            // the point as a radial point.

            if (isPrevCurve && isThisCurve)
            {
                isRadial = true;

                // Get the curve parameters...

                IPosition prevcen = prevArc.Circle.Center;
                double    prevrad = prevArc.Circle.Radius;

                IPosition thiscen = thisArc.Circle.Center;
                double    thisrad = thisArc.Circle.Radius;

                // We only need to know the sense for one of the arcs
                bool iscw = thisArc.IsClockwise;

                // If the 2 curves do not have the same centre and radius,
                // see if they are really close (to the nearest centimeter
                // on the ground). In that case, use the average values for
                // the 2 curves. If they really are different curves, don't
                // treat this as a radial curve point -- treat it as a
                // curve end instead.

                IPosition centre = null;            // The centre to actually use

                if (!(prevcen == thiscen && Math.Abs(prevrad - thisrad) < Constants.TINY))
                {
                    double xc1 = prevcen.X;
                    double yc1 = prevcen.Y;
                    double xc2 = thiscen.X;
                    double yc2 = thiscen.Y;
                    double dxc = xc2 - xc1;
                    double dyc = yc2 - yc1;

                    if (Math.Abs(dxc) < 0.01 &&
                        Math.Abs(dyc) < 0.01 &&
                        Math.Abs(prevrad - thisrad) < 0.01)
                    {
                        // Close enough
                        centre = new Position(xc1 + dxc * 0.5, yc1 + dyc * 0.5);
                    }
                    else
                    {
                        isRadial   = false;
                        isCurveEnd = true;
                    }
                }
                else
                {
                    centre = prevcen;
                }

                // If the centre and radius were the same (or close enough),
                // define the radial bearing from the centre of the circle.
                // If the polygon is actually on the other side, reverse the
                // bearing so that it's directed INTO the polygon.

                if (isRadial)
                {
                    Debug.Assert(centre != null);
                    bearing = Geom.BearingInRadians(centre, m_Begin);
                    angle   = 0.0;
                    if (iscw != isPolLeft)
                    {
                        bearing += Constants.PI;
                    }
                }
            }

            // If we're not dealing with a radial curve (or we have curves that
            // don't appear to be radial)
            if (!isRadial)
            {
                // Get the clockwise angle from the last position of the
                // preceding face to the first position after the start
                // of this face. Since info is held in a clockwise cycle
                // around the polygon, this will always give us the exterior
                // angle.
                Turn reference = new Turn(m_Begin, prev.TailReference);
                angle = reference.GetAngleInRadians(this.HeadReference);

                // Define the bearing to use for projecting the point. It's
                // in the middle of the angle, but projected into the polygon.
                bearing = reference.BearingInRadians + angle * 0.5 + Constants.PI;
            }

            // Initialize the link at the start of the face
            List <PolygonLink> links = new List <PolygonLink>();
            PolygonLink        link  = new PolygonLink(beginPoint, isCurveEnd, isRadial, bearing, angle);

            links.Add(link);

            // Initialize links for any extra points
            if (m_ExtraPoints != null)
            {
                // Intermediate points can never be curve ends
                isCurveEnd = false;

                // If the face is a curve, they're radial points
                isRadial = isThisCurve;

                // Note any curve info
                double    radius;
                IPosition centre = null;
                bool      iscw   = false;

                if (isRadial)
                {
                    Debug.Assert(m_Divider.Line.LineGeometry is ICircularArcGeometry);
                    ICircularArcGeometry arc = (m_Divider.Line.LineGeometry as ICircularArcGeometry);
                    centre = arc.Circle.Center;
                    radius = arc.Circle.Radius;
                    iscw   = arc.IsClockwise;
                    angle  = 0.0;
                }

                for (uint i = 0; i < m_ExtraPoints.Length; i++)
                {
                    //IPointGeometry loc = m_ExtraPoints[i].Geometry;
                    PointFeature loc = m_ExtraPoints[i];

                    // Figure out the orientation bearing for the point
                    if (isRadial)
                    {
                        Debug.Assert(centre != null);
                        bearing = Geom.BearingInRadians(centre, loc);
                        if (iscw != isPolLeft)
                        {
                            bearing += Constants.PI;
                        }
                    }
                    else
                    {
                        // Get the exterior clockwise angle

                        IPointGeometry back;
                        IPointGeometry fore;

                        if (i == 0)
                        {
                            back = m_Begin;
                        }
                        else
                        {
                            back = m_ExtraPoints[i - 1].Geometry;
                        }

                        if (i == (m_ExtraPoints.Length - 1))
                        {
                            fore = m_End;
                        }
                        else
                        {
                            fore = m_ExtraPoints[i + 1].Geometry;
                        }


                        Turn reference = new Turn(loc, back);
                        angle = reference.GetAngleInRadians(fore);

                        // Define the bearing to use for projecting the point. It's
                        // in the middle of the angle, but projected into the polygon.
                        bearing = reference.BearingInRadians + angle * 0.5 + Constants.PI;
                    }

                    link = new PolygonLink(m_ExtraPoints[i], isCurveEnd, isRadial, bearing, angle);
                    links.Add(link);
                }
            }

            return(links.ToArray());
        }