Ejemplo n.º 1
0
        /// <summary>
        /// Creates new <c>LineStringGeometry</c> that corresponds to the supplied positions.
        /// </summary>
        /// <param name="data">The positions defining the line.</param>
        public LineStringGeometry(IPointGeometry[] data)
        {
            if (data==null || data.Length<2)
                throw new ArgumentException();

            m_Data = data;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Gets the point on this line that is closest to a specified position.
        /// </summary>
        /// <param name="p">The position to search from.</param>
        /// <param name="tol">Maximum distance from line to the search position</param>
        /// <returns>The closest position (null if the line is further away than the specified
        /// max distance)</returns>
        internal override IPosition GetClosest(IPointGeometry p, ILength tol)
        {
            // Get the perpendicular point (or closest end)
            IPointGeometry s = Start;
            IPointGeometry e = End;
            double         xp, yp;

            BasicGeom.GetPerpendicular(p.X, p.Y, s.X, s.Y, e.X, e.Y, out xp, out yp);

            // Ignore if point is too far away
            double t  = tol.Meters;
            double dx = p.X - xp;

            if (dx > t)
            {
                return(null);
            }

            double dy = p.Y - yp;

            if (dy > t)
            {
                return(null);
            }

            double dsq = (dx * dx + dy * dy);

            if (dsq > t * t)
            {
                return(null);
            }

            return(new Position(xp, yp));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Creates a new <c>FindClosestQuery</c> (and executes it). The result of the query
        /// can then be obtained through the <c>Result</c> property.
        /// </summary>
        /// <param name="index">The spatial index to search</param>
        /// <param name="p">The search position.</param>
        /// <param name="radius">The search tolerance (expected to be greater than zero).</param>
        /// <param name="types">The type of objects to look for.</param>
        internal FindClosestQuery(ISpatialIndex index, IPosition p, ILength radius, SpatialType types)
        {
            if (types == 0)
            {
                throw new ArgumentNullException("Spatial type(s) not specified");
            }

            // If the user hasn't been specific, ensure we don't search for polygons!
            SpatialType useTypes = (types == SpatialType.All ? SpatialType.Feature : types);

            Debug.Assert((useTypes & SpatialType.Polygon) == 0);

            // It's important to round off to the nearest micron. Otherwise you might not
            // get the desired results in situations where the search radius is zero.
            m_Position = PositionGeometry.Create(p);

            m_Radius   = radius;
            m_Types    = types;
            m_Result   = null;
            m_Distance = m_Radius.Meters;

            // The query will actually involve a square window, not a circle.
            IWindow x = new Window(m_Position, radius.Meters * 2.0);

            index.QueryWindow(x, useTypes, OnQueryHit);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Delegate that's called whenever the index finds text with a window that overlaps the query window
        /// </summary>
        /// <param name="item">The item to process (expected to be some sort of <c>TextFeature</c>)</param>
        /// <returns>True (always), indicating that the query should continue.</returns>
        private bool OnTextFound(ISpatialObject item)
        {
            // Ignore test that's already been built
            TextFeature text = (TextFeature)item;

            if (text.IsBuilt)
            {
                return(true);
            }

            if (text.IsTopological)
            {
                // Get the label's reference position.
                IPointGeometry posn = text.GetPolPosition();

                // Try to find enclosing polygon
                if (m_Polygon.IsEnclosing(posn))
                {
                    m_Result = text;
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="cc">Object for holding any displayed dialogs</param>
 /// <param name="action">The action that initiated this command</param>
 /// <param name="start">Point initially selected at start of command</param>
 internal NewLineUI(IControlContainer cc, IUserAction action, PointFeature start)
     : base(cc, action)
 {
     m_Start        = start;
     m_End          = null;
     m_CurrentPoint = start;
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Checks whether this closed shape overlaps a line
        /// </summary>
        /// <param name="shape">Positions defining a closed outline (the last position
        /// must coincide with the first position). At least 3 positions.</param>
        /// <param name="shapeWindow">The extent of <paramref name="shape"/></param>
        /// <param name="line">The line to compare with the shape</param>
        /// <returns>True if the shape overlaps the line</returns>
        internal bool IsOverlap(LineGeometry line)
        {
            // Get the window of the line
            IWindow lwin = line.Extent;

            // The two windows have to overlap.
            if (!m_Extent.IsOverlap(lwin))
            {
                return(false);
            }

            // If either end of the line falls inside this shape, we've got overlap.
            IPointGeometry p = line.Start;

            if (m_Extent.IsOverlap(p) && Geom.IsPointInClosedShape(this.Data, p))
            {
                return(true);
            }

            p = line.End;
            if (m_Extent.IsOverlap(p) && Geom.IsPointInClosedShape(this.Data, p))
            {
                return(true);
            }

            // The only thing left is a possible interesection between
            // the shape and the line.
            return(IsIntersect(line));
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Checks whether a location falls in the sector lying between the BC and EC
        /// of a circular arc. The only condition is that the location has an appropriate
        /// bearing with respect to the bearings of the BC & EC (i.e. the location does not
        /// necessarily lie ON the arc).
        /// </summary>
        /// <param name="pos">The position to check</param>
        /// <param name="lintol">Linear tolerance, in meters on the ground (locations that are
        /// beyond the BC or EC by up to this much will also be regarded as "in-sector").</param>
        /// <returns>True if position falls in the sector defined by this arc</returns>
        public static bool IsInSector(ICircularArcGeometry g, IPosition pos, double lintol)
        {
            // If the arc is a complete circle, it's ALWAYS in sector.
            if (IsCircle(g))
            {
                return(true);
            }

            // Express the curve's start & end points in local system,
            // ordered clockwise.
            IPointGeometry start = g.First;
            IPointGeometry end   = g.Second;

            // Get the centre of the circular arc.
            IPosition centre = g.Circle.Center;

            // If we have a linear tolerance, figure out the angular equivalent.
            if (lintol > MathConstants.TINY)
            {
                double angtol = lintol / g.Circle.Radius;
                return(BasicGeom.IsInSector(pos, centre, start, end, angtol));
            }
            else
            {
                return(BasicGeom.IsInSector(pos, centre, start, end, 0.0));
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Creates a new <c>FindPointContainerQuery</c> (and executes it). The result of the query
        /// can then be obtained through the <c>Result</c> property.
        /// </summary>
        /// <param name="index">The spatial index to search</param>
        /// <param name="point">The position you want the container for</param>
        internal FindPointContainerQuery(ISpatialIndex index, IPointGeometry p)
        {
            m_Point  = p;
            m_Result = null;
            IWindow w = new Window(p, p);

            index.QueryWindow(w, SpatialType.Polygon, OnQueryHit);

            // If we didn't get a result, but we skipped some candidates, check them now.
            if (m_Result == null && m_Candidates != null)
            {
                // If NONE of the polygon's islands enclose the search position, that's
                // the result we want.

                foreach (Polygon cand in m_Candidates)
                {
                    Debug.Assert(cand.HasAnyIslands);

                    if (!cand.HasIslandEnclosing(m_Point))
                    {
                        m_Result = cand;
                        return;
                    }
                }
            }
        }
        /// <summary>
        /// Creates a new <c>FindPointContainerQuery</c> (and executes it). The result of the query
        /// can then be obtained through the <c>Result</c> property.
        /// </summary>
        /// <param name="index">The spatial index to search</param>
        /// <param name="point">The position you want the container for</param>
        internal FindPointContainerQuery(ISpatialIndex index, IPointGeometry p)
        {
            m_Point = p;
            m_Result = null;
            IWindow w = new Window(p, p);
            index.QueryWindow(w, SpatialType.Polygon, OnQueryHit);

            // If we didn't get a result, but we skipped some candidates, check them now.
            if (m_Result==null && m_Candidates!=null)
            {
                // If NONE of the polygon's islands enclose the search position, that's
                // the result we want.

                foreach (Polygon cand in m_Candidates)
                {
                    Debug.Assert(cand.HasAnyIslands);

                    if (!cand.HasIslandEnclosing(m_Point))
                    {
                        m_Result = cand;
                        return;
                    }
                }
            }
        }
Ejemplo n.º 10
0
 public CircularArcGeometry(ICircleGeometry circle, IPointGeometry bc, IPointGeometry ec, bool isClockwise)
 {
     m_Circle = circle;
     m_BC = bc;
     m_EC = ec;
     m_IsClockwise = isClockwise;
 }
Ejemplo n.º 11
0
        void WriteArc(ArcGeometry line)
        {
            IPointGeometry center  = line.Circle.Center;
            double         bcAngle = GetAngle(center, line.BC);
            double         ecAngle = GetAngle(center, line.EC);

            Arc acLine = new Arc();

            acLine.Center = new Vector3d(center.X, center.Y, 0.0);
            acLine.Radius = line.Circle.Radius;

            // AutoCad arcs are *always* drawn counter-clockwise
            if (line.IsClockwise)
            {
                acLine.StartAngle = ecAngle;
                acLine.EndAngle   = bcAngle;
            }
            else
            {
                acLine.StartAngle = bcAngle;
                acLine.EndAngle   = ecAngle;
            }

            acLine.Layer = m_Layer;
            m_Dxf.AddEntity(acLine);
        }
Ejemplo n.º 12
0
        void ExportKey(TextFeature text)
        {
            Layer layer = m_Layers.GetLayer(text, m_ContinuousLineType, true);

            if (layer == null)
            {
                return;
            }

            // Get the label's key string. It HAS to be defined.
            string keystr = text.FormattedKey;

            if (String.IsNullOrEmpty(keystr))
            {
                return;
            }

            // Get the label's reference position.
            IPointGeometry refpos = text.GetPolPosition();

            // Define the position for AutoCad (bottom right corner).


            TextGeometry geom   = text.TextGeometry;
            Text         acText = new Text(geom.Text, GetVector(geom.Position), geom.Height);

            acText.Rotation = (float)geom.Rotation.Degrees;
            acText.Layer    = layer;

            m_Dxf.AddEntity(acText);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Checks whether any intersections occur at positions that do not coincide
        /// with the end points of a line.
        /// </summary>
        /// <param name="line">The line to check. This should be the same line that
        /// was supplied to the <c>IntersectionFinder</c> constructor that created THIS results
        /// object (doing otherwise doesn't make any sense).</param>
        /// <returns>TRUE if any intersection does not coincide with the end points
        /// of the specified line.</returns>
        internal bool IsSplitOn(ILineGeometry line)
        {
            // Get the locations of the line end points.
            IPointGeometry start = line.Start;
            IPointGeometry end   = line.End;

            // Go through each intersection, looking for one that does
            // not correspond to the line ends.

            foreach (IntersectionData d in m_Data)
            {
                IPointGeometry loc1 = new PointGeometry(d.P1);
                if (!start.IsCoincident(loc1) && !end.IsCoincident(loc1))
                {
                    return(true);
                }

                if (d.IsGraze)
                {
                    /*
                     * Huh? This was the original, but it always ended up returning true.
                     *
                     *          IPointGeometry loc2 = PointGeometry.New(d.P2);
                     * if (!start.IsCoincident(loc2) && !end.IsCoincident(loc2))
                     *  return true;
                     *
                     * return true;
                     */
                    return(true);
                }
            }

            return(false);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Adds a termination point (or re-use a point if it happens to be the offset point).
        /// </summary>
        /// <param name="loc">The location for the termination point.</param>
        /// <returns>The point feature at the termination point (may be the position that was
        /// used to define the offset to the parallel line).</returns>
        PointFeature AddPoint(IPosition loc)
        {
            CadastralMapModel map = CadastralMapModel.Current;

            // Add the split point (with default entity type). If a
            // point already exists at the location, you'll get back
            // that point instead.

            // We do this in case the user has decided to
            // terminate on a line connected to the offset point
            // that defines the offset to the parallel (which the
            // UI lets the user do).

            PointFeature p = this.OffsetPoint;

            if (p != null)
            {
                IPointGeometry pg = PointGeometry.Create(loc);
                if (p.IsCoincident(pg))
                {
                    return(p);
                }
            }

            p = map.AddPoint(p, map.DefaultPointType, this);
            p.SetNextId();

            return(p);
        }
Ejemplo n.º 15
0
 public CircularArcGeometry(ICircleGeometry circle, IPosition bc, IPosition ec, bool isClockwise)
 {
     m_Circle      = circle;
     m_BC          = PositionGeometry.Create(bc);
     m_EC          = PositionGeometry.Create(ec);
     m_IsClockwise = isClockwise;
 }
Ejemplo n.º 16
0
 public CircularArcGeometry(ICircleGeometry circle, IPosition bc, IPosition ec, bool isClockwise)
 {
     m_Circle = circle;
     m_BC = PositionGeometry.Create(bc);
     m_EC = PositionGeometry.Create(ec);
     m_IsClockwise = isClockwise;
 }
Ejemplo n.º 17
0
        /// <summary>
        /// Writes the content of this instance to a persistent storage area.
        /// </summary>
        /// <param name="editSerializer">The mechanism for storing content.</param>
        public override void WriteData(EditSerializer editSerializer)
        {
            base.WriteData(editSerializer);

            editSerializer.WriteBool(DataField.Topological, IsTopological);

            IPointGeometry tp = Position;
            IPointGeometry pp = GetPolPosition();

            if (pp != null)
            {
                if (pp.Easting.Microns != tp.Easting.Microns || pp.Northing.Microns != tp.Northing.Microns)
                {
                    editSerializer.WriteInt64(DataField.PolygonX, pp.Easting.Microns);
                    editSerializer.WriteInt64(DataField.PolygonY, pp.Northing.Microns);
                }
            }

            // RowText is problematic on deserialization because the database rows might not
            // be there. To cover that possibility, use a proxy object.
            if (m_Geom is RowTextGeometry)
            {
                editSerializer.WritePersistent <TextGeometry>(DataField.Type, new RowTextContent((RowTextGeometry)m_Geom));
            }
            else
            {
                editSerializer.WritePersistent <TextGeometry>(DataField.Type, m_Geom);
            }
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Checks an array of positions that purportedly correspond to a circular arc, to see
        /// whether the data is directed clockwise or not. No checks are made to confirm that
        /// the data really does correspond to a circular arc.
        /// </summary>
        /// <param name="pts">The positions defining an arc</param>
        /// <param name="center">The position of the centre of the circle that the arc lies on.</param>
        /// <returns>True if the data is ordered clockwise.</returns>
        public static bool IsClockwise(IPointGeometry[] pts, IPointGeometry center)
        {
            // To determine the direction, we must locate two successive
            // vertices that lie in the same quadrant (with respect to the
            // circle center).

            QuadVertex start = new QuadVertex(center, pts[0]);
            QuadVertex end   = null;

            for (int i = 1; i < pts.Length; i++, start = end)
            {
                // Pick up the position at the end of the line segment.
                end = new QuadVertex(center, pts[i]);

                // If both ends of the segment are in the same quadrant,
                // see which one comes first. The result tells us whether
                // the curve is clockwise or not.

                if (start.Quadrant == end.Quadrant)
                {
                    return(start.GetTanAngle() < end.GetTanAngle());
                }
            }

            // Something has gone wrong if we got here!
            Debug.Assert(1 == 2);
            return(true);
        }
Ejemplo n.º 19
0
 /// <summary>
 /// Creates a new <c>FindPointQuery</c> (and executes it). The result of the query
 /// can then be obtained through the <c>Result</c> property.
 /// </summary>
 /// <param name="index">The spatial index to search</param>
 /// <param name="point">The position of interest</param>
 internal FindPointQuery(ISpatialIndex index, IPointGeometry p)
 {
     m_Point = p;
     m_Result = null;
     IWindow w = new Window(p, p);
     index.QueryWindow(w, SpatialType.Point, OnQueryHit);
 }
Ejemplo n.º 20
0
        /// <summary>
        /// Returns a code indicating the relative position of a location with respect to
        /// a rectangular window (the Cohen & Sutherland clipping algorithm).
        /// </summary>
        /// <param name="p">The position of interest</param>
        /// <param name="sw">South-west corner of window</param>
        /// <param name="ne">North-east corner of window</param>
        /// <returns></returns>
        internal static byte GetPositionCode(IPointGeometry p, IPointGeometry sw, IPointGeometry ne)
        {
            byte code = 0;
            long e    = p.Easting.Microns;

            if (e < sw.Easting.Microns) // p west of sw
            {
                code |= 0x01;
            }
            else if (e > ne.Easting.Microns) // p east of ne
            {
                code |= 0x02;
            }

            long n = p.Northing.Microns;

            if (n < sw.Northing.Microns) // p south of sw
            {
                code |= 0x04;
            }
            else if (n > ne.Northing.Microns) // p north of ne
            {
                code |= 0x08;
            }

            return(code);
        }
Ejemplo n.º 21
0
 public CircularArcGeometry(ICircularArcGeometry g)
 {
     m_Circle      = g.Circle;
     m_BC          = g.BC;
     m_EC          = g.EC;
     m_IsClockwise = g.IsClockwise;
 }
Ejemplo n.º 22
0
 public CircularArcGeometry(ICircleGeometry circle, IPointGeometry bc, IPointGeometry ec, bool isClockwise)
 {
     m_Circle      = circle;
     m_BC          = bc;
     m_EC          = ec;
     m_IsClockwise = isClockwise;
 }
Ejemplo n.º 23
0
        /// <summary>
        /// Ensure that this label knows it's enclosing polygon.
        /// </summary>
        /// <returns>True if label successfully associated with polygon.</returns>
        internal void SetPolygon()
        {
            // Return if this label is already associated with a polygon (or the
            // label was previously found to be inside nothing)
            if (IsBuilt)
            {
                return;
            }

            // If this is a non-topological label, mark is as "built"
            // and return (it should have been previously marked as built).
            if (IsTopological)
            {
                // Get the label's reference position.
                IPointGeometry posn = GetPolPosition();

                // Try to find enclosing polygon
                ISpatialIndex index = CadastralMapModel.Current.Index;
                Polygon       enc   = new FindPointContainerQuery(index, posn).Result;
                if (enc != null)
                {
                    enc.ClaimLabel(this);
                }
            }

            SetBuilt(true);
        }
Ejemplo n.º 24
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="cc">Object for holding any displayed dialogs</param>
 /// <param name="action">The action that initiated this command</param>
 /// <param name="start">Point initially selected at start of command</param>
 internal NewLineUI(IControlContainer cc, IUserAction action, PointFeature start)
     : base(cc, action)
 {
     m_Start = start;
     m_End = null;
     m_CurrentPoint = start;
 }
Ejemplo n.º 25
0
        /// <summary>
        /// Defines orientation info.
        /// </summary>
        /// <param name="orient">The orientation position.</param>
        void SetOrient(IPosition orient)
        {
            if (m_Divider == null)
            {
                return;
            }

            // Get the position of the point that the divider meets.
            IPointGeometry loc = (m_IsStart ? m_Divider.From : m_Divider.To);

            // Figure out the deltas of the orientation point with respect to the point.
            double dx = orient.X - loc.X;
            double dy = orient.Y - loc.Y;

            // What quadrant are we in?
            m_Quadrant = WhatQuadrant(dx, dy);

            // Convert the deltas into an IJ coordinate system. When we
            // calculate I/J, it will always give us tan(angle) in each
            // successive quadrant, with the start of the quadrant resulting
            // in an angle of zero, and the end of the quadrant resulting in
            // an angle just less than infinity.

            switch (m_Quadrant)
            {
            case Quadrant.NE:
            {
                m_DeltaI = dx;
                m_DeltaJ = dy;
                return;
            }

            case Quadrant.SE:
            {
                m_DeltaI = -dy;
                m_DeltaJ = dx;
                return;
            }

            case Quadrant.SW:
            {
                m_DeltaI = -dx;
                m_DeltaJ = -dy;
                return;
            }

            case Quadrant.NW:
            {
                m_DeltaI = dy;
                m_DeltaJ = -dx;
                return;
            }
            }

            string msg = String.Format("Orientation.SetOrient - Quadrant error at {0:0.0000}N {1:0.0000}E",
                                       loc.Y, loc.X);

            throw new Exception(msg);
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Generates an approximation of a circular arc.
        /// </summary>
        /// <param name="tol">The maximum chord-to-circumference distance.</param>
        /// <returns></returns>
        public static IPointGeometry[] GetApproximation(ICircularArcGeometry g, ILength tol)
        {
            // Get info about the circle the curve lies on.
            IPosition center = g.Circle.Center;
            double    radius = g.Circle.Radius;

            // Determine the change in bearing which will satisfy the specified tolerance
            // (if no tolerance has been specified, arbitrarily use a tolerance of 1mm on the ground).
            double tolm  = (tol.Meters > Double.Epsilon ? tol.Meters : 0.001);
            double dbear = Math.Acos((radius - tolm) / radius);

            IPointGeometry start = g.BC;
            IPointGeometry end   = g.EC;
            bool           iscw  = g.IsClockwise;

            // Get the total angle subtended by the curve.
            Turn   reft   = new Turn(center, start);
            double totang = reft.GetAngleInRadians(end); // clockwise

            if (!iscw)
            {
                totang = MathConstants.PIMUL2 - totang;
            }

            // Figure out how many positions we'll generate
            int nv = (int)(totang / dbear); // truncate

            Debug.Assert(nv >= 0);

            // Handle special case of very short arc.
            if (nv == 0)
            {
                return new IPointGeometry[] { start, end }
            }
            ;

            // Sign the delta-bearing the right way.
            if (!iscw)
            {
                dbear = -dbear;
            }

            // Get the initial bearing to the first position along the curve.
            double curbear = reft.BearingInRadians + dbear;

            // Append positions along the length of the curve.
            List <IPointGeometry> result = new List <IPointGeometry>(nv);

            result.Add(start);

            for (int i = 0; i < nv; i++, curbear += dbear)
            {
                IPosition p = BasicGeom.Polar(center, curbear, radius);
                result.Add(PositionGeometry.Create(p));
            }

            result.Add(end);
            return(result.ToArray());
        }
Ejemplo n.º 27
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Annotation"/> class with the
 /// <see cref="FontStyle"/> property set to <see cref="System.Drawing.FontStyle.Regular"/>.
 /// </summary>
 /// <param name="text">The annotation text.</param>
 /// <param name="position">The position for the text (center-baseline aligned).</param>
 /// <param name="height">The height of the text (in meters on the ground).</param>
 /// <param name="rotation">The rotation (in radians clockwise from horizontal).</param>
 internal Annotation(string text, IPosition position, double height, double rotation)
 {
     m_Text = text;
     m_Position = PointGeometry.Create(position);
     m_Height = height;
     m_Rotation = new RadianValue(rotation);
     m_FontStyle = FontStyle.Regular;
 }
Ejemplo n.º 28
0
        internal HorizontalRay(IPosition start, double distance)
        {
            if (distance < 0.0)
                throw new ArgumentOutOfRangeException();

            m_Start = PointGeometry.Create(start);
            m_EndX = start.X + distance;
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Creates a new <c>FindPointQuery</c> (and executes it). The result of the query
        /// can then be obtained through the <c>Result</c> property.
        /// </summary>
        /// <param name="index">The spatial index to search</param>
        /// <param name="point">The position of interest</param>
        internal FindPointQuery(ISpatialIndex index, IPointGeometry p)
        {
            m_Point  = p;
            m_Result = null;
            IWindow w = new Window(p, p);

            index.QueryWindow(w, SpatialType.Point, OnQueryHit);
        }
Ejemplo n.º 30
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Annotation"/> class with the
 /// <see cref="FontStyle"/> property set to <see cref="System.Drawing.FontStyle.Regular"/>.
 /// </summary>
 /// <param name="text">The annotation text.</param>
 /// <param name="position">The position for the text (center-baseline aligned).</param>
 /// <param name="height">The height of the text (in meters on the ground).</param>
 /// <param name="rotation">The rotation (in radians clockwise from horizontal).</param>
 internal Annotation(string text, IPosition position, double height, double rotation)
 {
     m_Text      = text;
     m_Position  = PointGeometry.Create(position);
     m_Height    = height;
     m_Rotation  = new RadianValue(rotation);
     m_FontStyle = FontStyle.Regular;
 }
Ejemplo n.º 31
0
        /// <summary>
        /// Cuts back a horizontal line segment to the closest intersection with this line.
        /// Used in point in polygon.
        /// </summary>
        /// <param name="s">Start of horizontal segment.</param>
        /// <param name="e">End of segment (will be modified if segment intersects this line)</param>
        /// <param name="status">Return code indicating whether an error has arisen (returned
        /// as 0 if no error).</param>
        /// <returns>True if the horizontal line was cut back.</returns>
        internal override bool GetCloser(IPointGeometry s, ref PointGeometry e, out uint status)
        {
            status = 0;

            // Remember the initial end of segment
            PointGeometry initEnd = new PointGeometry(e);

            // Represent the horizontal segment in a class of its own
            HorizontalRay hseg = new HorizontalRay(s, e.X - s.X);

            if (!hseg.IsValid)
            {
                status = 1;
                return(false);
            }

            IPointGeometry[] data = this.Data;

            // Get relative position code for the start of the line. If it's
            // somewhere on the horizontal segment, cut the line back.
            byte scode = Geom.GetPositionCode(data[0], s, e);

            if (scode == 0)
            {
                e = new PointGeometry(Start);
            }

            // Loop through each line segment, testing the end of each segment
            // against the horizontal segment.
            byte ecode;

            for (int i = 1; i < data.Length; scode = ecode, i++)
            {
                // Get the position code for the end of the line segment
                ecode = Geom.GetPositionCode(data[i], s, e);

                // If it's coincident with the horizontal segment, cut the
                // line back. Otherwise see whether there is any potential
                // intersection to cut back to.

                if (ecode == 0)
                {
                    e = new PointGeometry(data[i]);
                }
                else if ((scode & ecode) == 0)
                {
                    IPosition x = null;
                    if (hseg.Intersect(data[i - 1], data[i], ref x))
                    {
                        e = new PointGeometry(x);
                    }
                }
            }

            // Return flag to indicate whether we got closer or not.
            return(!e.IsCoincident(initEnd));
        }
Ejemplo n.º 32
0
        internal HorizontalRay(IPosition start, double distance)
        {
            if (distance < 0.0)
            {
                throw new ArgumentOutOfRangeException();
            }

            m_Start = PointGeometry.Create(start);
            m_EndX  = start.X + distance;
        }
Ejemplo n.º 33
0
        /// <summary>
        /// Sees whether the orientation of the new text should be altered. This
        /// occurs if the auto-angle capability is enabled, and the specified
        /// position is close to any visible line.
        /// </summary>
        /// <param name="refpos">The current mouse position (reference position
        /// for the new label)</param>
        /// <returns>True if the orientation angle got changed.</returns>
        bool CheckOrientation(IPointGeometry refpos)
        {
            // Return if the auto-angle function is disabled.
            if (!m_IsAutoAngle)
            {
                return(false);
            }

            // Return if the auto-position function is enabled
            if (m_IsAutoPos)
            {
                return(false);
            }

            // Try to get an orientation line
            LineFeature orient = GetOrientation(refpos);

            if (!Object.ReferenceEquals(orient, m_Orient))
            {
                ErasePainting();
            }

            m_Orient = null;
            if (orient == null)
            {
                return(false);
            }

            // Locate the closest point on the line (we SHOULD find it,
            // but if we don't, just bail out)
            ISpatialDisplay display = ActiveDisplay;
            ILength         tol     = new Length(0.002 * display.MapScale);
            IPosition       closest = orient.LineGeometry.GetClosest(refpos, tol);

            if (closest == null)
            {
                return(false);
            }

            m_Orient = orient;
            if (m_Orient == null)
            {
                return(false);
            }

            // Highlight the new orientation line
            m_Orient.Render(display, new HighlightStyle());

            // Get the rotation angle
            IPointGeometry cg  = PointGeometry.Create(closest);
            double         rot = m_Orient.LineGeometry.GetRotation(cg);

            SetRotation(rot);
            return(true);
        }
Ejemplo n.º 34
0
        /// <summary>
        /// Handles mouse-move.
        /// </summary>
        /// <param name="pos">The new position of the mouse</param>
        internal override void MouseMove(IPosition pos)
        {
            // If we previously drew a text outline, erase it now.
            EraseRect();

            // Find the polygon (if any) that encloses the mouse position.
            CadastralMapModel map   = CadastralMapModel.Current;
            ISpatialIndex     index = map.Index;
            IPointGeometry    pg    = PointGeometry.Create(pos);
            Polygon           enc   = new FindPointContainerQuery(index, pg).Result;

            // If it's different from what we previously had, remember the
            // new enclosing polygon.
            if (!Object.ReferenceEquals(enc, m_Polygon))
            {
                // If we had something before, and we filled it, erase
                // the fill now.
                //DrawPolygon(false);

                // Remember the polygon we're now enclosed by (if any).
                m_Polygon = enc;

                // Draw the new polygon.
                //DrawPolygon(true);

                // Ensure any calculated position has been cleared
                m_AutoPosition = null;

                // See if a new orientation applies
                CheckOrientation(pg);

                // If the enclosing polygon does not have a label, use the
                // standard cursor and fill the polygon. Otherwise use the
                // gray cursor.
                SetCommandCursor();
            }

            // Draw a rectangle representing the outline of the text.
            if (m_IsAutoPos && m_Polygon != null)
            {
                if (m_AutoPosition == null)
                {
                    m_AutoPosition = m_Polygon.GetLabelPosition(Width, Height);
                }
            }

            if (m_IsAutoPos && m_AutoPosition != null)
            {
                DrawText(m_AutoPosition);
            }
            else
            {
                DrawText(pos);
            }
        }
Ejemplo n.º 35
0
        internal override bool LButtonDown(IPosition p)
        {
            // Quit if we don't have a selected line
            if (m_Line == null)
            {
                AbortCommand();
                return(false);
            }

            // Get the position on the selected line that is closest
            // to the supplied position.
            ISpatialDisplay draw = ActiveDisplay;
            ILength         tol  = new Length(0.001 * draw.MapScale);
            IPointGeometry  pg   = PointGeometry.Create(p);
            IPosition       pos  = m_Line.LineGeometry.GetClosest(pg, tol);

            if (pos == null)
            {
                MessageBox.Show("You appear to be moving the mouse too fast");
                return(false);
            }

            // Obtain the position ratio
            uint pr = AttachPointOperation.GetPositionRatio(m_Line, pos);

            // Attach a new point to the line
            AttachPointOperation op = null;

            try
            {
                op = new AttachPointOperation(m_Line, pr);
                FeatureFactory ff = new FeatureFactory(op);
                ff.PointType = m_PointType;
                op.Execute(ff);

                // Ensure the draw includes the extra point (perhaps a bit of overkill to
                // draw just one point).
                Controller.RefreshAllDisplays();
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.StackTrace, ex.Message);
                return(true);
            }

            // Exit the command if we're not supposed to repeat
            if (!m_Repeat)
            {
                AbortCommand();
            }

            return(true);
        }
Ejemplo n.º 36
0
        /// <summary>
        /// Constructor for a grazing intersection. If the supplied positions are
        /// actually closer than the coordinate resolution (1 micron), a simple
        /// intersection will be defined.
        /// </summary>
        /// <param name="p1">The 1st intersection.</param>
        /// <param name="p2">The 2nd intersection.</param>
        IntersectionData(IPointGeometry p1, IPointGeometry p2)
        {
            m_X1 = p1;
            if (!p1.IsCoincident(p2))
            {
                m_X2 = p2;
            }

            m_SortValue = 0.0;
            m_Context1  = 0;
            m_Context2  = 0;
        }
Ejemplo n.º 37
0
        /// <summary>
        /// Checks whether this window overlaps a position
        /// </summary>
        /// <param name="p">The position to examine</param>
        /// <returns>True if the position overlaps this window (may be exactly
        /// coincident with the perimeter)</returns>
        internal bool IsOverlap(IPointGeometry p)
        {
            ulong val = SpatialIndex.ToUnsigned(p.Easting.Microns);

            if (val < m_X.Min || val > m_X.Max)
            {
                return(false);
            }

            val = SpatialIndex.ToUnsigned(p.Northing.Microns);
            return(val >= m_Y.Min && val <= m_Y.Max);
        }
Ejemplo n.º 38
0
        void WriteSegment(SegmentGeometry line)
        {
            Line           acLine = new Line();
            IPointGeometry start  = line.Start;

            acLine.StartPoint = new Vector3d(start.X, start.Y, 0.0);
            IPointGeometry end = line.End;

            acLine.EndPoint = new Vector3d(end.X, end.Y, 0.0);
            acLine.Layer    = m_Layer;
            m_Dxf.AddEntity(acLine);
        }
Ejemplo n.º 39
0
        /// <summary>
        /// Constructs a new <c>MultiSegmentGeometry</c>
        /// </summary>
        /// <param name="start">The point at the start of the connection.</param>
        /// <param name="end">The point at the end of the connection.</param>
        /// <param name="positions">The ground positions to pack. The first & last positions must exactly
        /// match the position of the supplied end points.</param>
        internal MultiSegmentGeometry(ITerminal start, ITerminal end, IPointGeometry[] positions)
            : base(start, end)
        {
            if (positions==null || positions.Length==0)
                throw new ArgumentNullException();

            if (positions.Length<=2)
                throw new ArgumentException("Not enough points for a multi-segment");

            if (!start.IsCoincident(positions[0]))
                throw new ArgumentException("Start point doesn't coincide with first position");

            if (!end.IsCoincident(positions[positions.Length-1]))
                throw new ArgumentException("End point doesn't coincide with last position");

            m_Data = positions;
            m_Extent = LineStringGeometry.GetExtent(this);
        }
Ejemplo n.º 40
0
        /// <summary>
        /// Creates a new <c>FindClosestQuery</c> (and executes it). The result of the query
        /// can then be obtained through the <c>Result</c> property.
        /// </summary>
        /// <param name="index">The spatial index to search</param>
        /// <param name="p">The search position.</param>
        /// <param name="radius">The search tolerance (expected to be greater than zero).</param>
        /// <param name="types">The type of objects to look for.</param>
        internal FindClosestQuery(ISpatialIndex index, IPosition p, ILength radius, SpatialType types)
        {
            if (types==0)
                throw new ArgumentNullException("Spatial type(s) not specified");

            // If the user hasn't been specific, ensure we don't search for polygons!
            SpatialType useTypes = (types==SpatialType.All ? SpatialType.Feature : types);
            Debug.Assert((useTypes & SpatialType.Polygon)==0);

            // It's important to round off to the nearest micron. Otherwise you might not
            // get the desired results in situations where the search radius is zero.
            m_Position = PositionGeometry.Create(p);

            m_Radius = radius;
            m_Types = types;
            m_Result = null;
            m_Distance = m_Radius.Meters;

            // The query will actually involve a square window, not a circle.
            IWindow x = new Window(m_Position, radius.Meters * 2.0);
            index.QueryWindow(x, useTypes, OnQueryHit);
        }
Ejemplo n.º 41
0
        /// <summary>
        /// Intersects 2 clockwise arcs that coincide with the perimeter of a circle.
        /// </summary>
        /// <param name="xsect">Intersection results.</param>
        /// <param name="circle">The circle the arcs coincide with</param>
        /// <param name="bc1">BC for 1st arc.</param>
        /// <param name="ec1">EC for 1st arc.</param>
        /// <param name="bc2">BC for 2nd arc.</param>
        /// <param name="ec2">EC for 2nd arc.</param>
        /// <returns>The number of intersections (0, 1, or 2). If non-zero, the intersections
        /// will be grazes.</returns>
        static uint ArcIntersect( IntersectionResult xsect
            , ICircleGeometry circle
            , IPointGeometry bc1
            , IPointGeometry ec1
            , IPointGeometry bc2
            , IPointGeometry ec2)
        {
            // Define the start of the clockwise arc as a reference line,
            // and get the clockwise angle to it's EC.
            Turn reft = new Turn(circle.Center, bc1);
            double sector = reft.GetAngleInRadians(ec1);

            // Where do the BC and EC of the 2nd curve fall with respect
            // to the 1st curve's arc sector?
            double bcang = reft.GetAngleInRadians(bc2);
            double ecang = reft.GetAngleInRadians(ec2);

            if (bcang<sector)
            {
                if (ecang<bcang)
                {
                    xsect.Append(bc2, ec1);
                    xsect.Append(bc1, ec2);
                    return 2;
                }

                if (ecang<sector)
                    xsect.Append(bc2, ec2);
                else
                    xsect.Append(bc2, ec1);

                return 1;
            }

            // The BC of the 2nd curve falls beyond the sector of the 1st ...
            // so we can't have any graze if the EC is even further on.
            if (ecang>bcang)
                return 0;

            // One graze ...

            if (ecang<sector)
                xsect.Append(bc1, ec2);
            else
                xsect.Append(bc1, ec1);

            return 1;
        }
Ejemplo n.º 42
0
        /// <summary>
        /// Intersects a pair of clockwise arcs that sit on the same circle, and where ONE of
        /// the end points exactly matches.
        /// </summary>
        /// <param name="xsect">The intersection results.</param>
        /// <param name="circle">The circle the arcs coincide with</param>
        /// <param name="bc1">The BC of the 1st arc</param>
        /// <param name="ec1">The EC of the 1st arc</param>
        /// <param name="bc2">The BC of the 2nd arc -- the matching end</param>
        /// <param name="ec2">The EC of the 2nd arc</param>
        /// <param name="isStartMatch">Specify <c>true</c> if <paramref name="bc2"/> matches an end
        /// point of the 1st arc. Specify <c>false</c> if <paramref name="ec2"/> matches an end
        /// point of the 1st arc.</param>
        /// <returns>The number of intersections (always 1).</returns>
        static uint ArcEndIntersect( IntersectionResult xsect
            , ICircleGeometry circle
            , IPointGeometry bc1
            , IPointGeometry ec1
            , IPointGeometry bc2
            , IPointGeometry ec2
            , bool isStartMatch)
        {
            bool bmatch = bc1.IsCoincident(bc2);
            bool ematch = ec1.IsCoincident(ec2);

            // If the two curves share the same BC or same EC
            if (bmatch || ematch)
            {
                // We've got some sort of graze ...

                // Check for total graze.
                if (bmatch && ematch)
                    xsect.Append(bc1, ec1);
                else
                {
                    // We've therefore got a partial graze.

                    // If the length of this arc is longer than the other one, the graze is over the
                    // length of the other one, and vice versa. Since the two curves share the same
                    // radius and direction, the comparison just involves a comparison of the clockwise
                    // angles subtended by the arcs.

                    IPointGeometry centre = circle.Center;
                    double ang1 = new Turn(centre, bc1).GetAngleInRadians(ec1);
                    double ang2 = new Turn(centre, bc2).GetAngleInRadians(ec2);
                    bool isThisGraze = (ang1 < ang2);

                    if (isThisGraze)
                        xsect.Append(bc1, ec1);
                    else
                        xsect.Append(bc2, ec2);
                }
            }
            else
            {
                // The only intersection is at the common end.
                if (bc1.IsCoincident(bc2) || ec1.IsCoincident(bc2))
                    xsect.Append(bc2);
                else
                    xsect.Append(ec2);
            }

            return 1;
        }
Ejemplo n.º 43
0
        internal static uint Intersect( IntersectionResult results
            , IPointGeometry a
            , IPointGeometry b
            , IPointGeometry p
            , IPointGeometry q)
        {
            // 04-APR-2003: This isn't supposed to happen, but if we've somehow
            // got a null segment, it NEVER intersects anything.
            if (a.IsCoincident(b))
                return 0;

            // If the segment EXACTLY meets either end of the other segment,
            // it gets handled seperately.
            if (a.IsCoincident(p) || a.IsCoincident(q))
                return EndIntersect(results, p, q, a, b);

            if (b.IsCoincident(p) || b.IsCoincident(q))
                return EndIntersect(results, p, q, b, a);

            // Return if the windows don't overlap.
            Window winab = new Window(a, b);
            Window winpq = new Window(p, q);
            if (!winab.IsOverlap(winpq))
                return 0;

            // Check whether this line is completely coincident with the other one.
            // double tolsq = Constants.XYTOLSQ;
            double tolsq = (Constants.XYRES*Constants.XYRES);

            uint xcase = 0;
            if (PointGeometry.IsCoincidentWith(a, p, q, tolsq))
                xcase |= 0x08;
            if (PointGeometry.IsCoincidentWith(b, p, q, tolsq))
                xcase |= 0x04;

            if (xcase==12) // bits 1100
            {
                results.Append(a, b);
                return 1;
            }

            // Check the end points of the other line to this one.
            if (PointGeometry.IsCoincidentWith(p, a, b, tolsq))
                xcase |= 0x02;
            if (PointGeometry.IsCoincidentWith(q, a, b, tolsq))
                xcase |= 0x01;

            // Return intersections. Note that in cases 3,7,11, the intersections
            // are not necessarily ordered with respect to THIS segment.

            switch (xcase)
            {
                case 0:
                    {
                        // Try to get a simple intersection. Do not accept
                        // virtual intersections, since they should have been
                        // trapped via the calculation of the xcase.

                        double xi, yi;
                        int xcode = Geom.CalcIntersect(a.X, a.Y, b.X, b.Y, p.X, p.Y, q.X, q.Y, out xi, out yi, true);

                        if (xcode < 0)
                        {
                            results.Append(xi, yi, 0.0);
                            return 1;
                        }

                        return 0;
                    }

                case 1:
                    {
                        results.Append(q);
                        return 1;
                    }

                case 2:
                    {
                        results.Append(p);
                        return 1;
                    }

                case 3:
                    {
                        results.Append(p, q);	// order?
                        return 1;
                    }

                case 4:
                    {
                        results.Append(b);
                        return 1;
                    }

                case 5:
                    {
                        results.Append(q, b);
                        return 1;
                    }

                case 6:
                    {
                        results.Append(p, b);
                        return 1;
                    }

                case 7:
                    {
                        results.Append(p, q);	// order?
                        return 1;
                    }

                case 8:
                    {
                        results.Append(a);
                        return 1;
                    }

                case 9:
                    {
                        results.Append(a, q);
                        return 1;
                    }

                case 10:
                    {
                        results.Append(a, p);
                        return 1;
                    }

                case 11:
                    {
                        results.Append(p, q);	// order?
                        return 1;
                    }

            } // end switch

            throw new Exception("LineSegmentFeature.Intersect - Unexpected case");
        }
Ejemplo n.º 44
0
        /// <summary>
        /// Intersects a circle with a clockwise arc
        /// </summary>
        /// <param name="results"></param>
        /// <param name="c"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="arcCircle"></param>
        /// <returns></returns>
        static uint Intersect(IntersectionResult xsect, ICircleGeometry c, IPointGeometry start, IPointGeometry end, ICircleGeometry arcCircle)
        {
            // If the circles are IDENTICAL, we've got a graze.
            if (CircleGeometry.IsCoincident(c, arcCircle, Constants.XYRES))
            {
                xsect.Append(start, end);
                return 1;

            }

            // Intersect the 2 circles.
            IPosition x1, x2;
            uint nx = Intersect(c, arcCircle, out x1, out x2);

            // Return if no intersection.
            if (nx==0)
                return 0;

            // Remember the intersection(s) if they fall in the
            // curve's sector. Use a tolerance which is based on
            // the circle with the smaller radius (=> bigger angular
            // tolerance).

            IPointGeometry centre;
            double minrad;

            if (c.Radius < arcCircle.Radius)
            {
                minrad = c.Radius;
                centre = c.Center;
            }
            else
            {
                minrad = arcCircle.Radius;
                centre = arcCircle.Center;
            }

            //	const FLOAT8 angtol = XYTOL/minrad;
            //	const FLOAT8 angtol = 0.00002/minrad;	// 20 microns
            double angtol = 0.002/minrad;		// 2mm

            if (nx==1)
            {
                IPointGeometry loc = PointGeometry.Create(x1);
                if (Geom.IsInSector(loc, centre, start, end, angtol))
                {
                    xsect.Append(loc);
                    return 1;
                }

                return 0;
            }
            else
            {
                // Two intersections. They are valid if they fall within the curve's sector.
                IPointGeometry loc1 = PointGeometry.Create(x1);
                IPointGeometry loc2 = PointGeometry.Create(x2);
                uint nok=0;

                if (Geom.IsInSector(loc1, centre, start, end, angtol))
                {
                    xsect.Append(loc1);
                    nok++;
                }

                if (Geom.IsInSector(loc2, centre, start, end, angtol))
                {
                    xsect.Append(loc2);
                    nok++;
                }

                return nok;
            }
        }
Ejemplo n.º 45
0
        /// <summary>
        /// Sees whether the orientation of the new text should be altered. This
        /// occurs if the auto-angle capability is enabled, and the specified
        /// position is close to any visible line.
        /// </summary>
        /// <param name="refpos">The current mouse position (reference position
        /// for the new label)</param>
        /// <returns>True if the orientation angle got changed.</returns>
        bool CheckOrientation(IPointGeometry refpos)
        {
            // Return if the auto-angle function is disabled.
            if (!m_IsAutoAngle)
                return false;

            // Return if the auto-position function is enabled
            if (m_IsAutoPos)
                return false;

            // Try to get an orientation line
            LineFeature orient = GetOrientation(refpos);
            if (!Object.ReferenceEquals(orient, m_Orient))
                ErasePainting();

            m_Orient = null;
            if (orient == null)
                return false;

            // Locate the closest point on the line (we SHOULD find it,
            // but if we don't, just bail out)
            ISpatialDisplay display = ActiveDisplay;
            ILength tol = new Length(0.002 * display.MapScale);
            IPosition closest = orient.LineGeometry.GetClosest(refpos, tol);
            if (closest == null)
                return false;

            m_Orient = orient;
            if (m_Orient==null)
                return false;

            // Highlight the new orientation line
            m_Orient.Render(display, new HighlightStyle());

            // Get the rotation angle
            IPointGeometry cg = PointGeometry.Create(closest);
            double rot = m_Orient.LineGeometry.GetRotation(cg);
            SetRotation(rot);
            return true;
        }
Ejemplo n.º 46
0
        /// <summary>
        /// Returns a code indicating the relative position of a location with respect to
        /// a rectangular window (the Cohen & Sutherland clipping algorithm).
        /// </summary>
        /// <param name="p">The position of interest</param>
        /// <param name="sw">South-west corner of window</param>
        /// <param name="ne">North-east corner of window</param>
        /// <returns></returns>
        internal static byte GetPositionCode(IPointGeometry p, IPointGeometry sw, IPointGeometry ne)
        {
            byte code = 0;
            long e = p.Easting.Microns;

            if (e < sw.Easting.Microns) // p west of sw
                code |= 0x01;
            else if (e > ne.Easting.Microns) // p east of ne
                code |= 0x02;

            long n = p.Northing.Microns;
            if (n < sw.Northing.Microns) // p south of sw
                code |= 0x04;
            else if (n > ne.Northing.Microns) // p north of ne
                code |= 0x08;

            return code;
        }
Ejemplo n.º 47
0
 /// <summary>
 /// Gets the point on this line that is closest to a specified position.
 /// </summary>
 /// <param name="p">The position to search from.</param>
 /// <param name="tol">Maximum distance from line to the search position</param>
 /// <returns>The closest position (null if the line is further away than the specified
 /// max distance)</returns>
 internal override IPosition GetClosest(IPointGeometry p, ILength tol)
 {
     return Make().GetClosest(p, tol);
 }
Ejemplo n.º 48
0
        /// <summary>
        /// Gets the point on this line that is closest to a specified position.
        /// </summary>
        /// <param name="p">The position to search from.</param>
        /// <param name="tol">Maximum distance from line to the search position</param>
        /// <returns>The closest position (null if the line is further away than the specified
        /// max distance)</returns>
        internal override IPosition GetClosest(IPointGeometry p, ILength tol)
        {
            // Get the perpendicular point (or closest end)
            IPointGeometry s = Start;
            IPointGeometry e = End;
            double xp, yp;
            BasicGeom.GetPerpendicular(p.X, p.Y, s.X, s.Y, e.X, e.Y, out xp, out yp);

            // Ignore if point is too far away
            double t = tol.Meters;
            double dx = p.X - xp;
            if (dx > t)
                return null;

            double dy = p.Y - yp;
            if (dy > t)
                return null;

            double dsq = (dx*dx + dy*dy);
            if (dsq > t*t)
                return null;

            return new Position(xp, yp);
        }
Ejemplo n.º 49
0
 /// <summary>
 /// Cuts back a horizontal line segment to the closest intersection with this line.
 /// Used in point in polygon.
 /// </summary>
 /// <param name="s">Start of horizontal segment.</param>
 /// <param name="e">End of segment (will be modified if segment intersects this line)</param>
 /// <param name="status">Return code indicating whether an error has arisen (returned
 /// as 0 if no error).</param>
 /// <returns>True if the horizontal line was cut back.</returns>
 internal override bool GetCloser(IPointGeometry s, ref PointGeometry e, out uint status)
 {
     return Make().GetCloser(s, ref e, out status);
 }
Ejemplo n.º 50
0
        /// <summary>
        /// Calculates an angle that is parallel to this line (suitable for adding text)
        /// </summary>
        /// <param name="p">A significant point on the line (not used).</param>
        /// <returns>The rotation (in radians, clockwise from horizontal). Always greater
        /// than or equal to 0.0</returns>
        internal override double GetRotation(IPointGeometry p)
        {
            double xs = Start.X;
            double ys = Start.Y;
            double xe = End.X;
            double ye = End.Y;
            double dx = xe - xs;
            double dy = ye - ys;

            // Horizontal (to nearest mm)
            double ady = Math.Abs(dy);
            if (ady < 0.001)
                return 0.0;

            // Vertical (to nearest mm)
            double adx = Math.Abs(dx);
            if (adx < 0.001)
                return MathConstants.PIDIV2;

            // Get result in range (0,PIDIV2)
            double rotation = Math.Atan(ady/adx);

            // Stuff in the NE and SW quadrants needs to be tweaked.
            if ((dx < 0.0 && dy < 0.0) || (dx > 0.0 && dy > 0.0))
            {
                rotation = -rotation;
                if (rotation < 0.0)
                    rotation += MathConstants.PIMUL2;
            }

            return rotation;
        }
Ejemplo n.º 51
0
 // Circle
 internal uint Intersect(IPointGeometry center, double radius)
 {
     ICircleGeometry circle = new CircleGeometry(center, radius);
     return m_IntersectedObject.LineGeometry.IntersectCircle(this, circle);
 }
Ejemplo n.º 52
0
        /// <summary>
        /// Sees whether the orientation of the new text should be altered. This
        /// occurs if the auto-orient capability is enabled, and the specified
        /// position is close to any visible lne.
        /// </summary>
        /// <param name="posn">The position to use for making the check.</param>
        /// <returns></returns>
        LineFeature GetOrientation(IPointGeometry posn)
        {
            // The ground tolerance is 2mm at the draw scale.
            ISpatialDisplay display = ActiveDisplay;
            double tol = 0.002 * display.MapScale;

            // If we previously selected something, see if the search point
            // lies within tolerance. If so, there's no change.
            if (m_Orient != null)
            {
                double dist = m_Orient.Distance(posn).Meters;
                if (dist < tol)
                    return m_Orient;
            }

            // Get the map to find the closest line
            CadastralMapModel map = CadastralMapModel.Current;
            ISpatialIndex index = map.Index;
            return (index.QueryClosest(posn, new Length(tol), SpatialType.Line) as LineFeature);
        }
Ejemplo n.º 53
0
        /// <summary>
        /// Intersects this segment with another segment, where at least one end of the
        /// segment exactly coincides with one end of the other segment. 
        /// </summary>
        /// <param name="xsect">The intersection results.</param>
        /// <param name="start">The start of the other segment.</param>
        /// <param name="end">The end of the other segment.</param>
        /// <param name="xend">The end of THIS segment that coincides with one end
        /// of the other one (the geometry for either m_Start or m_End).</param>
        /// <param name="othend">The other end of THIS segment (may or may not coincide
        /// with one end of the other segment).</param>
        /// <returns>The number of intersections (always 1).</returns>
        static uint EndIntersect( IntersectionResult xsect
            , IPointGeometry start
            , IPointGeometry end
            , IPointGeometry xend
            , IPointGeometry othend)
        {
            // If the other end of this segment coincides with either end
            // of the other segment, we've got a total graze.
            if (othend.IsCoincident(start) || othend.IsCoincident(end))
            {
                xsect.Append(start, end);
                return 1;
            }

            // Get the locations that define the longer segment, together
            // with the location that is different from the exactly matching end.

            IPointGeometry startLong;
            IPointGeometry endLong;
            IPointGeometry test;

            if (Geom.DistanceSquared(xend, othend) < Geom.DistanceSquared(start, end))
            {
                test = othend;
                startLong = start;
                endLong = end;
            }
            else
            {
                startLong = xend;
                endLong = othend;

                if (xend.IsCoincident(start))
                    test = end;
                else
                    test = start;
            }

            // If it is coincident (to within the resolution) AND the
            // position ratio of the perpendicular point is ON this
            // segment, it's a graze.

            double tolsq = (Constants.XYRES * Constants.XYRES);

            if (PointGeometry.IsCoincidentWith(test, startLong, endLong, tolsq))
            {
                double prat = Geom.GetPositionRatio(test.X
                                                   , test.Y
                                                   , startLong.X
                                                   , startLong.Y
                                                   , endLong.X
                                                   , endLong.Y);

                if (prat>0.0 && prat<1.0)
                {
                    xsect.Append(xend, test);
                    return 1;
                }
            }

            // ONE intersection at the end that exactly matches.
            xsect.Append(xend);
            return 1;
        }
Ejemplo n.º 54
0
 /// <summary>
 /// Calculates an angle that is parallel to this line (suitable for adding text)
 /// </summary>
 /// <param name="p">A significant point on the line. In the case of lines
 /// that are multi-segments, the individual line segment that contains this
 /// position should be used to obtain the angle.</param>
 /// <returns>The rotation (in radians, clockwise from horizontal)</returns>
 internal override double GetRotation(IPointGeometry p)
 {
     return Make().GetRotation(p);
 }
Ejemplo n.º 55
0
        /// <summary>
        /// Intersects a line segment with a clockwise arc, where at least one end of the
        /// segment exactly coincides with one end of the arc.
        /// </summary>
        /// <param name="xsect">The intersection results.</param>
        /// <param name="bc">The start of the clockwise arc.</param>
        /// <param name="ec">The end of the clockwise arc.</param>
        /// <param name="circle">The circle on which the arc lies.</param>
        /// <param name="xend">The end of the segment that coincides with one end of the arc.</param>
        /// <param name="othend">The other end of the segment (may or may not coincide
        /// with one end of the arc).</param>
        /// <returns>The number of intersections (either 1 or 2).</returns>
        static uint EndIntersect( IntersectionResult xsect
            , IPointGeometry bc
            , IPointGeometry ec
            , ICircleGeometry circle
            , IPointGeometry xend
            , IPointGeometry othend)
        {
            // If the other end is INSIDE the circle, the matching end
            // location is the one and only intersection. Allow a tolerance
            // that is consistent with the resolution of data (3 microns).
            IPointGeometry centre = circle.Center;
            double radius = circle.Radius;
            double minrad = (radius-Constants.XYTOL);
            double minrsq = (minrad*minrad);
            double othdsq = Geom.DistanceSquared(othend, centre);

            if (othdsq < minrsq)
            {
                xsect.Append(xend);
                return 1;
            }

            // If the other end of the segment also coincides with either
            // end of the curve, the segment is a chord of the circle that
            // the curve lies on. However, if it's REAL close, we need to
            // return it as a graze ...

            if (othend.IsCoincident(bc) || othend.IsCoincident(ec))
            {
                // Get the midpoint of the chord.
                IPosition midseg = Position.CreateMidpoint(xend, othend);

                // If the distance from the centre of the circle to the
                // midpoint is REAL close to the curve, we've got a graze.

                if (Geom.DistanceSquared(midseg, centre) > minrsq)
                {
                    xsect.Append(xend, othend);
                    return 1;
                }

                // Two distinct intersections.
                xsect.Append(xend);
                xsect.Append(othend);
                return 2;
            }

            // If the other end is within tolerance of the circle, project
            // it to the circle and see if it's within the curve's sector.
            // If not, it's not really an intersect.

            double maxrad = (radius+Constants.XYTOL);
            double maxrsq = (maxrad*maxrad);

            if ( othdsq < maxrsq )
            {
                // Check if the angle to the other end is prior to the EC.
                // If not, it's somewhere off the curve.
                Turn reft = new Turn(centre, bc);
                if (reft.GetAngleInRadians(othend) > reft.GetAngleInRadians(ec))
                {
                    xsect.Append(xend);
                    return 1;
                }

                // And, like above, see if the segment grazes or not ...

                // Get the midpoint of the chord.
                IPosition midseg = Position.CreateMidpoint(xend, othend);

                // If the distance from the centre of the circle to the
                // midpoint is REAL close to the curve, we've got a graze.

                if (Geom.DistanceSquared(midseg, centre) > minrsq)
                {
                    xsect.Append(xend, othend);
                    return 1;
                }

                // Two distinct intersections.
                xsect.Append(xend);
                xsect.Append(othend);
                return 2;
            }

            // That leaves us with the other end lying somewhere clearly
            // outside the circle. However, we could still have a graze.

            // Make sure the BC/EC are EXACTLY coincident with the circle (they
            // may have been rounded off if the curve has been intersected
            // with a location that's within tolerance of the circle).

            IPosition trueBC, trueEC;
            Position.GetCirclePosition(bc, centre, radius, out trueBC);
            Position.GetCirclePosition(ec, centre, radius, out trueEC);

            // As well as the end of the segment that meets the curve.
            IPosition trueXend = (xend.IsCoincident(bc) ? trueBC : trueEC);

            // Intersect the segment with the complete circle (this does
            // NOT return an intersection at the other end, even if it is
            // really close ... we took care of that above).

            // The intersection must lie ON the segment (not sure about this though).

            IPosition othvtx = othend;
            IPosition x1, x2;
            bool isTangent;
            uint nx = Geom.IntersectCircle(centre, radius, trueXend, othvtx, out x1, out x2, out isTangent, true);

            // If we got NOTHING, that's unexpected, since one end exactly coincides
            // with the circle. In that case, just return the matching end (NOT
            // projected to the true position).
            if (nx==0)
            {
                xsect.Append(xend);
                return 1;
            }

            // If we got 2 intersections, pick the one that's further away than the matching end.
            if (nx==2 && Geom.DistanceSquared(x2, trueXend) > Geom.DistanceSquared(x1, trueXend))
                x1 = x2;

            // That leaves us with ONE intersection with the circle ... now
            // confirm that it actually intersects the arc!

            Turn refbc = new Turn(centre, trueBC);
            double eangle = refbc.GetAngleInRadians(trueEC);
            double xangle = refbc.GetAngleInRadians(x1);

            if (xangle > eangle)
            {
                xsect.Append(xend);
                return 1;
            }

            // Get the midpoint of the segment that connects the intersection to the true end.
            IPosition midx = Position.CreateMidpoint(trueXend, x1);

            // If the midpoint does NOT graze the circle, we've got 2 distinct intersections.
            // 25-NOV-99: Be realistic about it (avoid meaningless sliver polygons that are
            // less than 0.1mm wide on the ground).

            // if ( midx.DistanceSquared(centre) < minrsq ) {
            double rdiff = Geom.Distance(midx, centre) - radius;
            if (Math.Abs(rdiff) > 0.0001)
            {
                xsect.Append(xend);
                xsect.Append(x1);
                return 2;
            }

            // We've got a graze, but possibly one that can be ignored(!). To
            // understand the reasoning here, bear in mind that lines get cut
            // only so that network topology can be formed. To do that, 2
            // orientation points are obtained for the lines incident on xend.
            // For the segment, the orientation point is the other end of the
            // segment. For the curve, it's a position 5 metres along the
            // curve (or the total curve length if it's not that long). So
            // if the graze is closer than the point that will be used to
            // get the orientation point, we can ignore the graze, since it
            // does not provide any useful info.

            // Given that it's a graze, assume that it's ok to work out
            // the arc distance as if it was straight.
            double dsqx = Geom.DistanceSquared(trueXend, x1);

            // If it's closer than 4m (allow some leeway, seeing how we've
            // just done an approximation), ignore the intersection. If it's
            // actually between 4 and 5 metres, it shouldn't do any harm
            // to make a split there (although it's kind of redundant).
            if (dsqx < 16.0)
            {
                xsect.Append(xend);
                return 1;
            }

            // It's a graze.
            //CeVertex vxend(xend);	// wants a vertex
            xsect.Append(xend, x1);
            return 1;
        }
Ejemplo n.º 56
0
        /// <summary>
        /// Intersects a line segment with the data describing a clockwise curve.
        /// </summary>
        /// <param name="result">The intersection results.</param>
        /// <param name="a">The start of the line segment</param>
        /// <param name="b">The end of the line segment</param>
        /// <param name="start">The start of the clockwise arc.</param>
        /// <param name="end">The end of the clockwise arc.</param>
        /// <param name="circle">The circle on which the arc lies.</param>
        /// <returns></returns>
        static uint Intersect( IntersectionResult result
            , IPointGeometry a
            , IPointGeometry b
            , IPointGeometry start
            , IPointGeometry end
            , ICircleGeometry circle)
        {
            // If the segment exactly meets either end of the curve, it gets handled seperately.
            if (a.IsCoincident(start) || a.IsCoincident(end))
                return EndIntersect(result, start, end, circle, a, b);

            if (b.IsCoincident(start) || b.IsCoincident(end))
                return EndIntersect(result, start, end, circle, b, a);

            // Get circle definition.
            IPointGeometry centre = circle.Center;
            double radius = circle.Radius;

            // Get up to 2 intersections with the circle.
            IPosition x1, x2;
            bool isGraze;
            uint nx = GetXCircle(a, b, centre, radius, out x1, out x2, out isGraze);

            // Return if no intersections with the circle.
            if (nx==0)
                return 0;

            // If an intersection is really close to the end of an arc, force it to be there.
            if (Geom.DistanceSquared(start, x1) < Constants.XYTOLSQ)
                x1 = start;
            else if (Geom.DistanceSquared(end, x1) < Constants.XYTOLSQ)
                x1 = end;

            if (nx==2)
            {
                if (Geom.DistanceSquared(start, x2) < Constants.XYTOLSQ)
                    x2 = start;
                else if (Geom.DistanceSquared(end, x2) < Constants.XYTOLSQ)
                    x2 = end;
            }

            // Determine whether the intersections fall within the sector
            // that's defined by the clockwise curve (grazes need a bit
            // more handling, so do that after we see how to do the non-
            // grazing case.

            if ( !isGraze )
            {
                PointGeometry xloc1 = PointGeometry.Create(x1);
                double lintol = Constants.XYTOL / radius;

                // If we only got one intersect, and it's out of sector, that's us done.
                if (nx==1)
                {
                    if (!BasicGeom.IsInSector(xloc1, centre, start, end, lintol))
                        return 0;

                    result.Append(x1);
                    return 1;
                }

                // Two intersections with the circle ...

                if (BasicGeom.IsInSector(xloc1, centre, start, end, lintol))
                    result.Append(x1);
                else
                    nx--;

                PointGeometry xloc2 = PointGeometry.Create(x2);

                if (BasicGeom.IsInSector(xloc2, centre, start, end, lintol))
                    result.Append(x2);
                else
                    nx--;

                return nx;
            }

            // That leaves us with the case where this segment grazes the
            // circle. GetXCircle is always supposed to return nx==2 in that
            // case (they're also supposed to be arranged in the same
            // direction as this segment).
            Debug.Assert(nx==2);

            // Get the clockwise angle subtended by the circular arc. Add
            // on a tiny bit to cover numerical comparison problems.
            Turn reft = new Turn(centre, start);
            double maxangle = reft.GetAngleInRadians(end) + Constants.TINY;

            // Get the clockwise angles to both intersections.
            double a1 = reft.GetAngleInRadians(x1);
            double a2 = reft.GetAngleInRadians(x2);

            // No graze if both are beyond the arc sector.
            if (a1>maxangle && a2>maxangle)
                return 0;

            // If both intersects are within sector, the only thing to watch
            // out for is a case where the graze apparently occupies more
            // than half a circle. In that case, we've actually got 2 grazes.

            if (a1<maxangle &&  a2<maxangle)
            {
                if (a2>a1 && (a2-a1)>Constants.PI)
                {
                    result.Append(x1, start);
                    result.Append(end, x2);
                    return 2;
                }

                if (a1>a2 && (a1-a2)>Constants.PI)
                {
                    result.Append(start, x2);
                    result.Append(x1, end);
                    return 2;
                }

                // So it's just a regular graze.
                result.Append(x1, x2);
                return 1;
            }

            // That's covered the cases where both intersects are either
            // both in sector, or both out. Return the intersection that's
            // in sector as a simple intersection (NOT a graze).

            // This is a cop-out. We should really try to figure out which
            // portion of the curve is grazing, but the logic for doing so
            // is surprisingly complex, being subject to a variety of special
            // cases. By returning the intersect as a simple intersect, I'm
            // hoping it covers most cases.

            if (a1 < maxangle)
                result.Append(x1);
            else
                result.Append(x2);

            return 1;
        }
Ejemplo n.º 57
0
        /// <summary>
        /// Attempts to find a location that can act as a terminal for a polygon boundary.
        /// This either refers to a user-perceived point feature, or an intersection
        /// point (as added via a prior call to <see cref="AddIntersection"/>).
        /// </summary>
        /// <param name="p">The position of interest</param>
        /// <remarks>The corresponding terminal (null if nothing found). This should either
        /// be an instance of <see cref="PointFeature"/> or <see cref="Intersection"/>.</remarks>
        internal ITerminal FindTerminal(IPointGeometry p)
        {
            // Search the base index for a real point feature
            PointFeature pf = (base.QueryClosest(p, Length.Zero, SpatialType.Point) as PointFeature);
            if (pf!=null)
                return pf;

            // Search for an intersection
            return (m_ExtraData.QueryClosest(p, Length.Zero, SpatialType.Point) as Intersection);
        }
Ejemplo n.º 58
0
        /// <summary>
        /// Intersects a line segment with a circle
        /// </summary>
        /// <param name="result"></param>
        /// <param name="a">The start of the line segment</param>
        /// <param name="b">The end  of the line segment</param>
        /// <param name="c">The center of the circle</param>
        /// <param name="r">The radius of the circle</param>
        /// <returns></returns>
        static uint Intersect(IntersectionResult result, IPointGeometry a, IPointGeometry b, IPointGeometry c, double r)
        {
            // Get intersections (if any). Return if nothing.
            IPosition x1, x2;
            bool isGraze;
            uint nx = GetXCircle(a, b, c, r, out x1, out x2, out isGraze);
            if (nx==0)
                return 0;

            // If we got just one intersection, it's a simple intersect (even
            // if it's a tangent to the circle).
            if (nx==1)
            {
                result.Append(x1);
                return 1;
            }

            // That leaves us with two intersections, which may or may
            // not be grazing the circle.

            if (isGraze)
            {
                result.Append(x1, x2);
                return 1;
            }

            result.Append(x1);
            result.Append(x2);
            return 2;
        }
Ejemplo n.º 59
0
        /// <summary>
        /// Cuts back a horizontal line segment to the closest intersection with this line.
        /// Used in point in polygon.
        /// </summary>
        /// <param name="s">Start of horizontal segment.</param>
        /// <param name="e">End of segment (will be modified if segment intersects this line)</param>
        /// <param name="status">Return code indicating whether an error has arisen (returned
        /// as 0 if no error).</param>
        /// <returns>True if the horizontal line was cut back.</returns>
        internal override bool GetCloser(IPointGeometry s, ref PointGeometry e, out uint status)
        {
            status = 0;

            // Remember the initial end of segment
            PointGeometry initEnd = new PointGeometry(e);

            // Represent the horizontal segment in a class of its own
            HorizontalRay hseg = new HorizontalRay(s, e.X-s.X);
            if (!hseg.IsValid)
            {
                status = 1;
                return false;
            }

            // Get relative position code for the start of the line. If it's
            // somewhere on the horizontal segment, cut the line back.
            byte scode = Geom.GetPositionCode(Start, s, e);
            if (scode==0)
                e = new PointGeometry(Start);

            // Get the position code for the end of the line segment
            byte ecode = Geom.GetPositionCode(End, s, e);

            // If it's coincident with the horizontal segment, cut the
            // line back. Otherwise see whether there is any potential
            // intersection to cut back to.

            if (ecode==0)
                e = new PointGeometry(End);
            else if ((scode & ecode)==0)
            {
                IPosition x = null;
                if (hseg.Intersect(Start, End, ref x))
                    e = new PointGeometry(x);
            }

            // Return flag to indicate whether we got closer or not.
            return (!e.IsCoincident(initEnd));
        }
Ejemplo n.º 60
0
 // Segment
 internal uint Intersect(IPointGeometry start, IPointGeometry end)
 {
     ILineSegmentGeometry seg = new LineSegmentGeometry(start, end);
     return m_IntersectedObject.LineGeometry.IntersectSegment(this, seg);
 }