/// <summary> /// Creates a new line section /// </summary> /// <param name="itemName">The name for the item involved</param> /// <param name="baseLine">The line that this section is part of</param> /// <param name="from">The point at the start of the section</param> /// <param name="to">The point at the end of the section</param> /// <returns>The created section (never null)</returns> internal override LineFeature CreateSection(string itemName, LineFeature baseLine, PointFeature from, PointFeature to) { IFeature f = new FeatureStub(this.Creator, InternalIdValue.Empty, baseLine.EntityType, null); return(new LineFeature(f, baseLine, from, to, baseLine.IsTopological)); }
/// <summary> /// Returns the point feature that is at the end of this leg. /// </summary> /// <param name="op">The operation that is expected to have created the end point.</param> /// <returns>The point object at the end. Null if the leg ends with an "OmitPoint", or /// the leg ends at a point that was not created by the specified operation (in the latter /// case, the leg might end at the very end of a connection path).</returns> internal PointFeature GetEndPoint(Operation op) { // If the very last feature for this leg is a point, that's the thing we want. Feature feat = m_Spans[NumSpan - 1].CreatedFeature; PointFeature point = (feat as PointFeature); if (point != null) { return(point); } // Otherwise the last feature should be a line object, so // we want IT'S end point (either active or inactive). LineFeature line = (feat as LineFeature); if (line != null) { point = line.EndPoint; if (Object.ReferenceEquals(point.Creator, op)) { return(point); } } return(null); }
/// <summary> /// Initializes a new instance of the <see cref="ArcGeometry"/> class /// using the data read from persistent storage. /// </summary> /// <param name="editDeserializer">The mechanism for reading back content.</param> internal ArcGeometry(EditDeserializer editDeserializer) : base(editDeserializer) { m_IsClockwise = editDeserializer.ReadBool(DataField.Clockwise); if (editDeserializer.IsNextField(DataField.Center)) { PointFeature center = editDeserializer.ReadFeatureRef <PointFeature>(this, DataField.Center); // The arc is the first arc attached to the circle. However, we cannot // calculate the radius just yet because the bc/ec points are not persisted // as part of the ArcGeometry definition (they are defined as part of the // LineFeature object that utilizes the ArcGeometry). // Even if we did have the bc/ec points at this stage, their positions will // only be available if the data came from an import (they will still be // undefined if the geometry is calculated, since calculation only occurs // after deserialization has been completed). if (center != null) { ApplyFeatureRef(DataField.Center, center); } } else { ArcFeature firstArc = editDeserializer.ReadFeatureRef <ArcFeature>(this, DataField.FirstArc); if (firstArc != null) { ApplyFeatureRef(DataField.FirstArc, firstArc); } } }
/* * /// <summary> * /// Updates the definition of this circle. * /// </summary> * /// <param name="center">The point at the center of the circle.</param> * /// <param name="radius">The radius of the circle, on the ground, in meters</param> * internal void MoveCircle(PointFeature center, double radius) * { * // Remove this circle (and attached arcs) from the spatial index * foreach (ArcFeature a in m_Arcs) * a.PreMove(); * * m_Center.MapModel.EditingIndex.RemoveCircle(this); * * // If the center location is changing then ensure that * // the old location no longer refers to this circle, * // and ensure the new one does. * * // 08-DEC-99: Note that there appears to be inconsistency * // in the cross-referencing of the center location to the * // circle. Some places seem to do it, while other don't. * // The extra reference shouldn't hurt, and at some stage * // in the future, it would be good to enforce this. * * if (!Object.ReferenceEquals(m_Center, center)) * { * m_Center.CutReference(this); * m_Center = center; * m_Center.AddReference(this); * } * * // Change the radius * m_Radius = radius; * * // Re-index this circle and any attached arcs (this should also * // mark the operations that created the arcs for rollforward). * m_Center.MapModel.EditingIndex.AddCircle(this); * foreach (ArcFeature a in m_Arcs) * a.PostMove(); * } */ /// <summary> /// Checks whether this circle is referenced to arcs that terminaye at /// a specific point. This excludes arcs that correspond to the whole circle. /// </summary> /// <param name="p">The point to look for</param> /// <returns>True if an incident arc was found.</returns> internal bool HasArcsAt(PointFeature p) { // A location to check has to be specified! if (p == null) { return(false); } // Loop through each arc (including inactive ones). foreach (ArcFeature a in m_Arcs) { // Skip if the arc represents the whole circle. if (a.Geometry.IsCircle) { continue; } // Check whether either end of the arc coincides with // the check location. if (p.IsCoincident(a.StartPoint) || p.IsCoincident(a.EndPoint)) { return(true); } } return(false); }
/// <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); }
/// <summary> /// Performs processing when a point is about to be moved. /// </summary> /// <param name="point">The point that is about to move</param> void HandlePointMoving(PointFeature point) { // Remove the point from the spatial index. point.RemoveIndex(); // Remove all dependent spatial objects from the index as well (usually // incident lines, but could also be circles) // Convert the supplied List to an array, since we may cut refs in // the loop below. if (point.Dependents != null) { IFeatureDependent[] deps = point.Dependents.ToArray(); if (deps != null) { // IFeatureDependent is implemented by Feature, Circle, and Operation. // For features and circles, this will remove them from the spatial index (for // line features, any polygon topology will also be marked for a rebuild). // For operations, OnFeatureMoving does nothing. foreach (IFeatureDependent fd in deps) { fd.OnFeatureMoving(point, this); } } } }
/// <summary> /// Defines geometry for this link (and undefines everything else). For use by <c>PolygonFace</c>. /// </summary> /// <param name="point">The point that coincides with this link position (may be null at /// system-generated split location)</param> /// <param name="isCurveEnd">Does the link location coincide with the BC/EC of a circular /// arc? If the link is regarded as a radial position, this must be false.</param> /// <param name="isRadial">Does the link fall somewhere along a circular curve?</param> /// <param name="bearing">The bearing of the bisector of the angle formed with adjacent /// link objects</param> /// <param name="angle">The clockwise angle formed with adjacent link positions (irrelevant /// if the link is a radial).</param> internal void Define(PointFeature point, bool isCurveEnd, bool isRadial, double bearing, double angle) { // Ensure everything is in it's default state ResetContent(); // Assign the supplied values m_Point = point; m_IsCurveEnd = isCurveEnd; m_IsRadial = isRadial; // If we're dealing with a radial, the angle is n/a. Otherwise // pick up a value that's less than 180 degrees (this simplifies // the test to see if we're dealing with a corner) if (m_IsRadial) { m_Angle = 0.0; } else { m_Angle = angle; if (m_Angle > Constants.PI) { m_Angle -= Constants.PI; } } // Important that the bearing is in range [0,PIMUL2), for use with Turn.GetAngle m_Bearing = bearing; if (m_Bearing >= Constants.PIMUL2) { m_Bearing -= Constants.PIMUL2; } }
/// <summary> /// Remembers a point that is about to be moved /// </summary> /// <param name="p">The point that is about to move</param> internal void AddMove(PointFeature p) { UpdateUndoMarker um = m_Moves.Peek(); Debug.Assert(um != null); um.AddMove(p); }
/// <summary> /// Tries to get a link between two points. /// </summary> /// <remarks> /// You can cycle through the links as soon as the constructor has been called, using /// a loop like: /// <code> /// /// PolygonSub sub = new PolygonSub(pol); /// PointFeature ps, pe; /// for (int i=0; sub.GetLink(i,out ps, out pe); i++); /// /// </code> /// </remarks> /// <param name="index">The index number of the link you want.</param> /// <param name="start">The point at the start of the link.</param> /// <param name="end">The point at the end of the link.</param> /// <returns>True if a link was returned</returns> internal bool GetLink(int index, out PointFeature start, out PointFeature end) { // Initialize return variables. start = end = null; // Loop through each point, checking to see whether it has a link. If so, // check if we have reached the desired index, and increment link count. This // may not be particularly efficient, but there shouldn't be that many links. PointFeature s, e; // Start and end of link int nLink = 0; // No links so far for (int i = 0; i < m_Links.Length; i++) { if (m_Links[i].GetLink(out s, out e)) { if (nLink == index) { start = s; end = e; return(true); } nLink++; } } // Specified index is greater than the number of links we actually have. return(false); }
void ExportPoint(PointFeature p) { IDirectPosition dp = new DirectPositionImpl(p.X, p.Y); IGeometry g = m_Factory.CreatePoint(dp); ExportGeometry(g); }
/// <summary> /// Attempts to make a distance out of this observation and a from-point. /// </summary> /// <param name="from">The point the distance was measured from.</param> /// <returns> /// The distance, in metres on the ground. If a distance cannot be deduced, /// this will be 0.0. NOTE: may actually be a distance on the mapping plane if this /// observation is an offset point. The caller needs to check.</returns> /// <devnote> /// This function was written to assist in the implementation of the /// Intersect Direction & Distance command, which allows a distance to be specified /// using an offset point. Since offsets and distance object do not inherit from some /// place where we could define a pure virtual, this function exists to make explicit /// checks on the sort of distance we have (I don't want to define stubs for all the /// other objects which won't be able to return a distance). Re-arranging the class /// hierarchy would be better. /// </devnote> internal ILength GetDistance(PointFeature from) { // It's easy if the observation is a distance object. Distance dist = (this as Distance); if (dist != null) { return(dist); } // Can't do anything if the from point is undefined. if (from == null) { return(Length.Zero); } // See if we have an offset point. If so, the distance is the // distance from the from-point to the offset-point. OffsetPoint offset = (OffsetPoint)this; if (offset == null) { return(Length.Zero); } return(new Length(Geom.Distance(offset.Point, from))); }
/// <summary> /// Creates a new <c>Circle</c> with the specified center and radius. /// </summary> /// <param name="center">The point at the center of the circle.</param> /// <param name="radius">The radius of the circle, in meters</param> internal Circle(PointFeature center, double radius) { m_Center = center; m_Radius = radius; m_Arcs = new List <ArcFeature>(); IsIndexed = false; }
/// <summary> /// Creates a new <c>SectionGeometry</c> /// </summary> /// <param name="baseLine">The line the section is based on (not null).</param> /// <param name="start">The point at the start of the section (coincident with /// the specified line)</param> /// <param name="end">The point at the end of the section (coincident with /// the specified line)</param> /// <exception cref="ArgumentNullException">If a null line was specified</exception> internal SectionGeometry(LineFeature baseLine, PointFeature start, PointFeature end) : base(start, end) { if (baseLine==null) throw new ArgumentNullException(); m_Base = baseLine; }
/// <summary> /// Associates this node with an additional feature /// </summary> /// <param name="p">The point making use of this node</param> /// <exception cref="ArgumentException">If the supplied point has a geometry that /// doesn't refer to this node</exception> internal void AttachPoint(PointFeature p) { if (!Object.ReferenceEquals(p.Geometry, this)) { throw new ArgumentException(); } m_Points.Add(p); }
/// <summary> /// Defines the attributes of this content /// </summary> /// <param name="reader">The reading tool</param> /// <remarks>Implements IXmlContent</remarks> public override void ReadAttributes(XmlContentReader reader) { m_Point = new PointFeature(); m_Point.ReadFeatureAttributes(reader); PointFeature p = reader.ReadFeatureByReference<PointFeature>("FirstPoint"); m_Point.Node = p.Node; p.Node.AttachPoint(m_Point); }
/// <summary> /// Creates any circle that's required for arcs that sit on this leg. This method must /// be called before making any calls to <see cref="CreateLine"/>. /// </summary> /// <param name="ff">The factory for creating new spatial features</param> /// <param name="itemName">The name for the item that represents the point at the center of the circle</param> /// <returns>The created circle (with an undefined radius)</returns> internal Circle CreateCircle(FeatureFactory ff, string itemName) { // Create a center point, and cross-reference to a new circle (with undefined radius) PointFeature center = ff.CreatePointFeature(itemName); m_Circle = new Circle(center, 0.0); m_Circle.AddReferences(); return(m_Circle); }
/// <summary> /// Defines the attributes of this content /// </summary> /// <param name="reader">The reading tool</param> /// <remarks>Implements IXmlContent</remarks> public override void ReadAttributes(XmlContentReader reader) { m_Point = new PointFeature(); m_Point.ReadFeatureAttributes(reader); PointFeature p = reader.ReadFeatureByReference <PointFeature>("FirstPoint"); m_Point.Node = p.Node; p.Node.AttachPoint(m_Point); }
/// <summary> /// Creates a new <c>SectionGeometry</c> /// </summary> /// <param name="baseLine">The line the section is based on (not null).</param> /// <param name="start">The point at the start of the section (coincident with /// the specified line)</param> /// <param name="end">The point at the end of the section (coincident with /// the specified line)</param> /// <exception cref="ArgumentNullException">If a null line was specified</exception> internal SectionGeometry(LineFeature baseLine, PointFeature start, PointFeature end) : base(start, end) { if (baseLine == null) { throw new ArgumentNullException(); } m_Base = baseLine; }
/// <summary> /// Creates a new <c>PathInfo</c> object /// </summary> /// <param name="from">The point where the path starts.</param> /// <param name="to">The point where the path ends.</param> internal PathInfo(PointFeature from, PointFeature to, Leg[] legs) { m_From = from; m_To = to; m_Legs = legs; m_IsAdjusted = false; m_Rotation = 0.0; m_ScaleFactor = 0.0; }
/// <summary> /// Create a new <c>PathInfo</c> object that corresponds to a previously /// saved connection path. For consistency with the other constructor, this /// does not attempt to adjust the path (the Rotation and ScaleFactory properties /// will retain zero values unless a call is made to Adjust). /// </summary> /// <param name="pop">The saved connection path</param> internal PathInfo(PathOperation pop) { m_From = pop.StartPoint; m_To = pop.EndPoint; m_Legs = pop.GetLegs(); m_IsAdjusted = false; m_Rotation = 0.0; m_ScaleFactor = 0.0; m_Precision = 0.0; }
/// <summary> /// Delegate that's called whenever the index finds a point that's inside the query window /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>PointFeature</c>)</param> /// <returns>True (always), indicating that the query should continue.</returns> private bool OnPointFound(ISpatialObject item) { PointFeature p = (PointFeature)item; if (m_ClosedShape.IsOverlap(p)) { m_Points.Add(p); } return(true); }
/// <summary> /// Initializes a new instance of the <see cref="Node"/> class that refers to /// the supplied array of points, all associated with the specified location. /// </summary> /// <param name="pts">The points that will be assigned this geometry (not null). /// Each point will be modified by referring its geometry to <c>this</c> node.</param> /// <param name="g">The geometry for the point (not null)</param> internal Node(PointFeature[] pts, PointGeometry g) : base(g) { if (pts==null) throw new ArgumentNullException(); m_Points = new List<PointFeature>(pts); // Ensure every point is associated with this node foreach (PointFeature p in pts) p.SetNode(this); }
/// <summary> /// Initializes a new instance of the <see cref="Node"/> class that refers to /// a specific point, with the specified location. /// </summary> /// <param name="p">The point that will be assigned this geometry (not null). /// Modified by referring its geometry to <c>this</c> node.</param> /// <param name="g">The geometry for the point (not null)</param> internal Node(PointFeature p, PointGeometry g) : base(g) { if (p==null) throw new ArgumentNullException(); m_Points = new List<PointFeature>(1); m_Points.Add(p); // Ensure the point is associated with this node p.SetNode(this); }
/// <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); }
/// <summary> /// Creates a new <see cref="LineFeature"/> (with <see cref="SegmentGeometry"/>) using the feature /// stub with the specified name. /// </summary> /// <param name="itemName">The name for the item involved</param> /// <param name="from">The point at the start of the line (not null).</param> /// <param name="to">The point at the end of the line (not null).</param> /// <returns>The created feature (null if there is no feature stub)</returns> internal override LineFeature CreateSegmentLineFeature(string itemName, PointFeature from, PointFeature to) { IFeature f = FindFeatureDescription(itemName); if (f == null) { return(null); } else { return(new LineFeature(f, from, to)); } }
/// <summary> /// Creates a new <see cref="LineFeature"/> using the session sequence number /// that was previously recorded via a call to <see cref="AddFeatureDescription"/>. /// <para/> /// Only the session sequence number will be used when creating the section (any /// entity type and feature ID that may have been presented through <see cref="AddFeatureDescription"/> /// will be ignored - the values from the parent line will be applied instead). /// </summary> /// <param name="field">The name for the item involved (must refer to information /// previously attached via a call to <see cref="AddFeatureDescription"/>)</param> /// <param name="baseLine">The line that's being subdivided</param> /// <param name="from">The point at the start of the section (not null).</param> /// <param name="to">The point at the end of the section (not null).</param> /// <returns>The created feature (null if a feature description was not previously added)</returns> /// <exception cref="InvalidOperationException">If information for the item has not been /// attached to this factory.</exception> LineFeature MakeSection(DataField field, LineFeature baseLine, PointFeature from, PointFeature to) { IFeature f = FindFeatureDescription(field.ToString()); if (f == null) { throw new InvalidOperationException(); } SectionGeometry section = new SectionGeometry(baseLine, from, to); return(baseLine.MakeSubSection(m_Operation, f.InternalId, section)); }
/// <summary> /// Assigns initial values to everything /// </summary> void ResetContent() { m_Point = null; m_Link = null; m_SideNumber = 0; m_Angle = 0.0; m_Bearing = 0.0; m_IsCurveEnd = false; m_IsEnd = false; m_IsRadial = false; m_LinkAngle = Constants.PIMUL2; m_NumIntersect = 0; }
/// <summary> /// Delegate that's called whenever the index finds an object with an extent that /// overlaps the query window. /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>PointFeature</c>)</param> /// <returns>True if the query should continue. False if a coincident point has been found.</returns> private bool OnQueryHit(ISpatialObject item) { Debug.Assert(item is PointFeature); PointFeature p = (PointFeature)item; if (p.Geometry.IsCoincident(m_Point)) { m_Result = p; return(false); } return(true); }
/// <summary> /// Returns any link information. /// </summary> /// <param name="from">The point where the link starts.</param> /// <param name="to">The point where the link ends.</param> /// <returns>True if a link has been returned. False if no link (in that case, /// the 2 return parameters come back as nulls).</returns> internal bool GetLink(out PointFeature from, out PointFeature to) { if (m_Link != null && !m_IsEnd) { from = m_Point; to = m_Link.Point; return(true); } else { from = to = null; return(false); } }
/// <summary> /// Splits a line into two sections, using the session sequence number /// that was previously recorded via a call to <see cref="AddFeatureDescription"/>. /// The original line will then be deactivated. /// <para/> /// Only the session sequence number will be used when creating the section (any /// entity type and feature ID that may have been presented through <see cref="AddFeatureDescription"/> /// will be ignored - the values from the parent line will be applied instead). /// </summary> /// <param name="baseLine">The line to split.</param> /// <param name="itemBefore">The name of the item for the section preceding the split.</param> /// <param name="x">The point that is common to the two sections</param> /// <param name="itemAfter">The name of the item for the section after the splot.</param> /// <param name="lineBefore">The created section prior to the split point (corresponding to <paramref name="itemBefore"/>)</param> /// <param name="lineAfter">The created section after the split point (corresponding to <paramref name="itemAfter"/>)</param> /// <exception cref="InvalidOperationException">If information for either item has not been /// attached to this factory.</exception> internal void MakeSections(LineFeature baseLine, DataField itemBefore, PointFeature x, DataField itemAfter, out LineFeature lineBefore, out LineFeature lineAfter) { lineBefore = lineAfter = null; // Split the line (the sections should get an undefined creation sequence). Note that // you cannot use the SplitLine method at this stage, because that requires defined // geometry. lineBefore = MakeSection(itemBefore, baseLine, baseLine.StartPoint, x); lineAfter = MakeSection(itemAfter, baseLine, x, baseLine.EndPoint); Deactivate(baseLine); }
/// <summary> /// Initializes a new instance of the <see cref="Node"/> class that refers to /// a specific point, with the specified location. /// </summary> /// <param name="p">The point that will be assigned this geometry (not null). /// Modified by referring its geometry to <c>this</c> node.</param> /// <param name="g">The geometry for the point (not null)</param> internal Node(PointFeature p, PointGeometry g) : base(g) { if (p == null) { throw new ArgumentNullException(); } m_Points = new List <PointFeature>(1); m_Points.Add(p); // Ensure the point is associated with this node p.SetNode(this); }
/// <summary> /// Creates a new <see cref="ArcFeature"/> using information previously /// recorded via a call to <see cref="AddFeatureDescription"/>. /// </summary> /// <param name="itemName">The name for the item involved</param> /// <param name="from">The point at the start of the line (not null).</param> /// <param name="to">The point at the end of the line (not null).</param> /// <returns>The new feature (null if a feature description was not previously added)</returns> internal override ArcFeature CreateArcFeature(string itemName, PointFeature from, PointFeature to) { IFeature f = FindFeatureDescription(itemName); if (f == null) { return(null); } // Circle construction lines may not have an entity type bool isPolBoundary = (f.EntityType == null ? false : f.EntityType.IsPolygonBoundaryValid); return(new ArcFeature(f, from, to, null, isPolBoundary)); }
/// <summary> /// Delegate that's called whenever the index finds an object with an extent that /// overlaps the query window. /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>PointFeature</c>)</param> /// <returns>True if the query should continue. False if a matching point has been found.</returns> private bool OnQueryHit(ISpatialObject item) { Debug.Assert(item is PointFeature); PointFeature p = (PointFeature)item; if (p.FormattedKey == m_Key) { m_Result = p; return(false); } return(true); }
private PointFeature EnsurePointExists(PointGeometry p, ILength tol, Operation creator) { PointFeature result = (PointFeature)m_Index.QueryClosest(p, tol, SpatialType.Point); if (result == null) { IEntity e = creator.MapModel.DefaultPointType; InternalIdValue id = CadastralMapModel.Current.WorkingSession.AllocateNextId(); result = new PointFeature(creator, id, e, p); m_Index.Add(result); m_Result.Add(result); } return(result); }
/// <summary> /// Attempts to make a distance out of this observation and a from-point. /// </summary> /// <param name="from">The point the distance was measured from.</param> /// <returns> /// The distance, in metres on the ground. If a distance cannot be deduced, /// this will be 0.0. NOTE: may actually be a distance on the mapping plane if this /// observation is an offset point. The caller needs to check.</returns> /// <devnote> /// This function was written to assist in the implementation of the /// Intersect Direction & Distance command, which allows a distance to be specified /// using an offset point. Since offsets and distance object do not inherit from some /// place where we could define a pure virtual, this function exists to make explicit /// checks on the sort of distance we have (I don't want to define stubs for all the /// other objects which won't be able to return a distance). Re-arranging the class /// hierarchy would be better. /// </devnote> internal ILength GetDistance(PointFeature from) { // It's easy if the observation is a distance object. Distance dist = (this as Distance); if (dist!=null) return dist; // Can't do anything if the from point is undefined. if (from==null) return Length.Zero; // See if we have an offset point. If so, the distance is the // distance from the from-point to the offset-point. OffsetPoint offset = (OffsetPoint)this; if (offset==null) return Length.Zero; return new Length(Geom.Distance(offset.Point, from)); }
/// <summary> /// Creates a new <see cref="ArcFeature"/> using information previously /// recorded via a call to <see cref="AddFeatureDescription"/>. /// </summary> /// <param name="itemName">The name for the item involved</param> /// <param name="from">The point at the start of the line (not null).</param> /// <param name="to">The point at the end of the line (not null).</param> /// <returns>The new feature (null if a feature description was not previously added)</returns> internal override ArcFeature CreateArcFeature(string itemName, PointFeature from, PointFeature to) { IFeature f = FindFeatureDescription(itemName); if (f == null) return null; // Circle construction lines may not have an entity type bool isPolBoundary = (f.EntityType == null ? false : f.EntityType.IsPolygonBoundaryValid); return new ArcFeature(f, from, to, null, isPolBoundary); }
/// <summary> /// Creates a new <see cref="LineFeature"/> (with <see cref="SegmentGeometry"/>) using the feature /// stub with the specified name. /// </summary> /// <param name="itemName">The name for the item involved</param> /// <param name="from">The point at the start of the line (not null).</param> /// <param name="to">The point at the end of the line (not null).</param> /// <returns>The created feature (null if there is no feature stub)</returns> internal override LineFeature CreateSegmentLineFeature(string itemName, PointFeature from, PointFeature to) { IFeature f = FindFeatureDescription(itemName); if (f == null) return null; else return new LineFeature(f, from, to); }
internal abstract void Paint(PointFeature point);
/// <summary> /// Delegate that's called whenever the index finds an object with an extent that /// overlaps the query window. /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>PointFeature</c>)</param> /// <returns>True if the query should continue. False if a matching point has been found.</returns> private bool OnQueryHit(ISpatialObject item) { Debug.Assert(item is PointFeature); PointFeature p = (PointFeature)item; if (p.FormattedKey == m_Key) { m_Result = p; return false; } return true; }
private PointFeature EnsurePointExists(PointGeometry p, ILength tol, Operation creator) { PointFeature result = (PointFeature)m_Index.QueryClosest(p, tol, SpatialType.Point); if (result==null) { IEntity e = creator.MapModel.DefaultPointType; InternalIdValue id = CadastralMapModel.Current.WorkingSession.AllocateNextId(); result = new PointFeature(creator, id, e, p); m_Index.Add(result); m_Result.Add(result); } return result; }
private Circle EnsureCircleExists(PointFeature center, double radius, ILength tol, Operation creator) { // The index refers to the data loaded from the current NTX file. It holds only // information for points & circles, so we should only find circles at this stage. Position p = new Position(center.X, center.Y+radius); ISpatialObject so = m_Index.QueryClosest(p, tol, SpatialType.Line); if (so==null) { so = new Circle(center, radius); m_Index.Add(so); } Debug.Assert(so is Circle); return (Circle)so; }
/// <summary> /// Creates spatial features (points and lines) for this face. The created /// features don't have any geometry. /// </summary> /// <param name="ff">The factory for creating new spatial features</param> /// <param name="startPoint">The point (if any) at the start of this leg. May be /// null in a situation where the preceding leg ended with an "omit point" directive.</param> /// <param name="lastPoint">The point that should be used for the very end /// of the leg (specify null if a point should be created at the end of the leg).</param> internal void CreateFeatures(FeatureFactory ff, PointFeature startPoint, PointFeature lastPoint) { PointFeature from = startPoint; PointFeature to = null; // The initial item sequence relates to the face itself. The first feature along the face will // have a sequence number one higher. uint maxSequence = this.Sequence.ItemSequence; int nSpan = m_Spans.Length; for (int i = 0; i < nSpan; i++, from = to) { SpanInfo span = GetSpanData(i); // If we have an end point, add it (so long as this span is not // at the very end of the connection path). to = null; maxSequence++; if (span.HasEndPoint) { if (i == (nSpan - 1)) to = lastPoint; if (to == null) to = ff.CreatePointFeature(maxSequence.ToString()); Debug.Assert(to != null); } // A line can only exist if both end points are defined (the "omit point" // directive may well be used to finish a leg without a point, so the first // span in the next leg can't have a line). maxSequence++; if (span.HasLine && from != null) { LineFeature line = this.Leg.CreateLine(ff, maxSequence.ToString(), from, to); line.ObservedLength = span.ObservedDistance; // Alternate faces should by non-topological. And mark as "void" so that it can be // skipped on export to AutoCad. if (FaceNumber == 2) { line.SetTopology(false); // should probably be false already line.IsVoid = true; } span.CreatedFeature = line; } else { span.CreatedFeature = to; } } }
/// <summary> /// Creates a new <c>LineFeature</c> /// </summary> /// <param name="creator">The operation that created the feature (not null)</param> /// <param name="id">The internal ID of this feature within the /// project that created it.</param> /// <param name="e">The entity type for the feature (not null)</param> /// <param name="g">The geometry defining the shape of the line (not null)</param> /// <note>To ensure that the start and end of all lines are instances of <see cref="PointFeature"/>, /// this constructor should always remain private.</note> protected LineFeature(Operation creator, InternalIdValue id, IEntity e, PointFeature start, PointFeature end, LineGeometry g) : base(creator, id, e, null) { if (g==null) throw new ArgumentNullException(); m_From = start; m_To = end; m_Geom = g; m_Topology = null; AddReferences(); // If the entity type denotes a topological boundary, initialize the topology. if (e.IsPolygonBoundaryValid) SetTopology(true); }
/// <summary> /// Initializes a new instance of the <see cref="LineFeature"/> class that corresponds to /// a section of another line, and records it as part of the map model. /// </summary> /// <param name="f">Basic information about the feature (not null).</param> /// <param name="baseLine">The line that this section is part of</param> /// <param name="start">The point at the start of the line</param> /// <param name="end">The point at the end of the line</param> /// <exception cref="ArgumentNullException">If either <paramref name="ent"/> or /// <paramref name="creator"/> is null.</exception> internal LineFeature(IFeature f, LineFeature baseLine, PointFeature start, PointFeature end, bool isTopological) : this(f, start, end, new SectionGeometry(baseLine, start, end), isTopological) { }
/// <summary> /// Reads data that was previously written using <see cref="WriteData"/> /// </summary> /// <param name="editDeserializer">The mechanism for reading back content.</param> /// <param name="from">The point at the start of the line</param> /// <param name="to">The point at the end of the line</param> /// <param name="isTopological">Does the line act as a polygon boundary </param> /// <param name="geom">The geometry for the line.</param> static void ReadData(EditDeserializer editDeserializer, out PointFeature from, out PointFeature to, out bool isTopological, out LineGeometry geom) { from = editDeserializer.ReadFeatureRef<PointFeature>(DataField.From); to = editDeserializer.ReadFeatureRef<PointFeature>(DataField.To); isTopological = editDeserializer.ReadBool(DataField.Topological); if (editDeserializer.IsNextField(DataField.Type)) { geom = editDeserializer.ReadPersistent<LineGeometry>(DataField.Type); // Ensure terminals have been defined (since there was no easy way to pass them // through to the LineGeometry constructor). geom.StartTerminal = from; geom.EndTerminal = to; // If we're dealing with a circular arc, and the bc/ec points have defined // positions (e.g. coming from an import), we can calculate the radius now. // Otherwise we'll need to wait until geometry has been calculated. // The radius is defined here only because it's consistent with older code. // It may well be better to leave the definition of circle radius till later // (i.e. do all circles after geometry has been calculated). ArcGeometry arc = (geom as ArcGeometry); if (arc != null) { Circle c = (Circle)arc.Circle; PointFeature center = c.CenterPoint; if (center.PointGeometry != null && from.PointGeometry != null) c.Radius = Geom.Distance(center.PointGeometry, from.PointGeometry); } } else { geom = new SegmentGeometry(from, to); } }
/// <summary> /// Creates a <c>LineFeature</c> consisting of a series of connected line segments. /// </summary> /// <param name="creator">The operation that created the feature (not null)</param> /// <param name="id">The internal ID of this feature within the project that created it.</param> /// <param name="e">The entity type for the feature.</param> /// <param name="start">The point at the start of the line</param> /// <param name="end">The point at the end of the line</param> /// <param name="data">The positions defining the shape of the line. The first position must /// coincide precisely with the supplied <paramref name="start"/>, and the last position /// must coincide precisely with <paramref name="end"/>. Expected to be more than two positions.</param> internal LineFeature(Operation creator, InternalIdValue id, IEntity e, PointFeature start, PointFeature end, PointGeometry[] data) : this(creator, id, e, start, end, new MultiSegmentGeometry(start, end, data)) { Debug.Assert(data.Length>2); Debug.Assert(start.Geometry.IsCoincident(data[0])); Debug.Assert(end.Geometry.IsCoincident(data[data.Length-1])); }
/// <summary> /// Remembers a point that is about to be moved /// </summary> /// <param name="p">The point that is about to move</param> internal void AddMove(PointFeature p) { Move m = new Move(p); m_Moves.Add(m); }
/// <summary> /// Initializes a new instance of the <see cref="Move"/> class, with an "old" position that /// corresponds to it's current position. /// </summary> /// <param name="feature">The point feature that is being moved.</param> internal Move(PointFeature feature) { m_Feature = feature; m_OldPosition = new PointGeometry(feature.PointGeometry); }
/// <summary> /// Ensures a point is visible on the active display (expands the draw window /// if necessary), and optionally selects it. /// </summary> /// <param name="p">The point that needs to be shown.</param> /// <param name="select">Specify true if the point should be selected.</param> internal void EnsureVisible(PointFeature p, bool select) { // Ensure the draw window shows the point. ISpatialDisplay display = ActiveDisplay; IWindow drawExtent = display.Extent; if (drawExtent==null || drawExtent.IsEmpty) display.DrawOverview(); else if (!drawExtent.IsOverlap(p)) display.Center = p; // Select the point if requested if (select) SetSelection(new Selection(p, p)); }
/// <summary> /// Initializes a new instance of the <see cref="LineFeature"/> class, and records it /// as part of the map model. /// </summary> /// <param name="f">Basic information about the feature (not null).</param> /// <param name="start">The point at the start of the line (not null).</param> /// <param name="end">The point at the end of the line (not null).</param> /// <exception cref="ArgumentNullException">If any parameter is null.</exception> internal LineFeature(IFeature f, PointFeature start, PointFeature end) : this(f, start, end, f.EntityType.IsPolygonBoundaryValid) { }
/// <summary> /// Creates a new <c>FindPointByIdQuery</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="key">The ID of interest.</param> internal FindPointByIdQuery(ISpatialIndex index, string key) { m_Key = key; m_Result = null; index.QueryWindow(null, SpatialType.Point, OnQueryHit); }
/// <summary> /// Initializes a new instance of the <see cref="LineFeature"/> class, and records it /// as part of the map model. /// </summary> /// <param name="f">Basic information about the feature (not null).</param> /// <param name="start">The point at the start of the line (not null).</param> /// <param name="end">The point at the end of the line (not null).</param> /// <param name="isTopological">Should the line be tagged as a polygon boundary?</param> /// <exception cref="ArgumentNullException">If any parameter is null.</exception> internal LineFeature(IFeature f, PointFeature start, PointFeature end, bool isTopological) : this(f, start, end, new SegmentGeometry(start, end), isTopological) { }
/// <summary> /// Initializes a new instance of the <see cref="LineFeature"/> class, and records it /// as part of the map model. /// </summary> /// <param name="iid">The internal ID for the feature.</param> /// <param name="fid">The (optional) user-perceived ID for the feature. If not null, /// this will be modified by cross-referencing it to the newly created feature.</param> /// <param name="ent">The entity type for the feature (not null)</param> /// <param name="creator">The operation creating the feature (not null). Expected to /// refer to an editing session that is consistent with the session ID that is part /// of the feature's internal ID.</param> /// <param name="start">The point at the start of the line (not null)</param> /// <param name="end">The point at the end of the line (not null)</param> /// <param name="g">The geometry for the line (could be null, although this is only really /// expected during deserialization)</param> /// <param name="isTopological">Does the line form part of a polygon boundary?</param> /// <exception cref="ArgumentNullException">If either <paramref name="ent"/> or /// <paramref name="creator"/> or <paramref name="start"/> or <paramref name="end"/> is null. /// </exception> protected LineFeature(IFeature f, PointFeature start, PointFeature end, LineGeometry g, bool isTopological) : base(f) { if (start == null || end == null) throw new ArgumentNullException(); m_From = start; m_To = end; m_Geom = g; m_Topology = null; // Don't cross-reference if we're dealing with a temporary feature if (!f.InternalId.IsEmpty) AddReferences(); if (isTopological) SetTopology(true); }
/// <summary> /// Delegate that's called whenever the index finds an object with an extent that /// overlaps the query window. /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>PointFeature</c>)</param> /// <returns>True if the query should continue. False if a coincident point has been found.</returns> private bool OnQueryHit(ISpatialObject item) { Debug.Assert(item is PointFeature); PointFeature p = (PointFeature)item; if (p.Geometry.IsCoincident(m_Point)) { m_Result = p; return false; } return true; }
/// <summary> /// Intersect this line with another line. /// </summary> /// <param name="line">The line to intersect with (not equal to THIS line)</param> /// <param name="closeTo">The point that the intersection should be closest to. /// Specify null if you don't care. In that case, if there are multiple intersections, /// you get the intersection that is closest to one of 3 points: the start of the /// direction line, the start of the line, or the end of the line.</param> /// <param name="xsect">The position of the intersection (if any). Null if not found.</param> /// <param name="closest">The default point that is closest to the intersection. Null if /// intersection wasn't found.</param> /// <returns>True if intersection was found.</returns> internal bool Intersect( LineFeature line , PointFeature closeTo , out IPosition xsect , out PointFeature closest) { // Initialize results xsect = null; closest = null; // Don't intersect a line with itself. if (Object.ReferenceEquals(this, line)) throw new Exception("Cannot intersect a line with itself."); // Intersect this line with the other one. IntersectionResult xres = new IntersectionResult(this); uint nx = line.LineGeometry.Intersect(xres); if (nx==0) return false; // Determine which terminal point is the best. double mindsq = Double.MaxValue; if (xres.GetCloserPoint(this.StartPoint, ref mindsq, ref xsect)) closest = this.StartPoint; if (xres.GetCloserPoint(this.EndPoint, ref mindsq, ref xsect)) closest = this.EndPoint; if (xres.GetCloserPoint(line.StartPoint, ref mindsq, ref xsect)) closest = line.StartPoint; if (xres.GetCloserPoint(line.EndPoint, ref mindsq, ref xsect)) closest = line.EndPoint; // If a close-to point has been specified, that overrides // everything else (however, doing the above has the desired // effect of defining the best of the default points). In // this case, we allow an intersection that coincides with // the line being intersected. if (closeTo!=null) xres.GetClosest(closeTo, out xsect, 0.0); return (xsect!=null); }
/// <summary> /// Creates a <c>LineFeature</c> consisting of a simple line segment. /// </summary> /// <param name="creator">The operation that created the feature (not null)</param> /// <param name="id">The internal ID of this feature within the project that created it.</param> /// <param name="e">The entity type for the feature.</param> /// <param name="start">The point at the start of the line</param> /// <param name="end">The point at the end of the line</param> internal LineFeature(Operation creator, InternalIdValue id, IEntity e, PointFeature start, PointFeature end) : this(creator, id, e, start, end, new SegmentGeometry(start, end)) { }
private Feature ImportSymbol(Ntx.Symbol symbol, Operation creator) { IEntity what = GetEntityType(symbol, SpatialType.Point); // Get the position Ntx.Position pos = symbol.Position; PointGeometry g = new PointGeometry(pos.Easting, pos.Northing); // Ignore positions at 0,0! if (g.Easting.Microns==0 && g.Northing.Microns==0) return null; InternalIdValue id = CadastralMapModel.Current.WorkingSession.AllocateNextId(); PointFeature p = new PointFeature(creator, id, what, g); /* static LOGICAL warned=FALSE; // debug // Get pointer to the map theme CeTheme theme(Symbol.GetTheme()); const CeTheme* const pTheme = theme.AddTheme(); // Get pointer to the entity CeEntity* pEntity = AddEntity(Symbol.GetpFeatureCode(),pTheme,VERTEX); // Get the position const CxPosition& pos = Symbol.GetPosition(); // For the time being ... if ( !warned && pos.Is3D() ) { AfxMessageBox("Elevation data is being stripped."); warned = TRUE; } // Add the position of the symbol. CeVertex vtx(pos.GetEasting(),pos.GetNorthing()) ; const CeLocation* pLoc = pMap->AddLocation(vtx); // If the location does not already have an associated point // feature, add one now (the location may have been previously // added via the import of a line). // Note that this version of AddPoint will always add a duplicate // point at the specified location. CePoint* pPoint = pMap->AddPoint((CeLocation* const)pLoc,pEntity); */ // Define foreign ID (if any) ... string keystr = symbol.Key; ForeignId fid = GetFeatureId(keystr); if (fid != null) fid.Add(p); return p; }