/// <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> /// Loads all circular arcs from an NTX file. /// </summary> /// <param name="fileName">The name of the NTX file to read from</param> /// <param name="creator">The edit that's being used to perform the import</param> /// <returns>The loaded features</returns> internal List <ArcFeature> LoadArcs(string fileName, Operation creator) { Ntx.File file = new Ntx.File(); try { file.Open(fileName); List <ArcFeature> result = new List <ArcFeature>(1000); ILength tol = GetPointMatchTolerance(file); while (file.GetMore()) { if (file.DataType == (int)Ntx.DataType.Line && file.Line.IsCurve) { ArcFeature f = ImportArc(file.Line, creator, tol); if (f != null) { result.Add((ArcFeature)f); } } } return(result); } finally { file.Close(); } }
/// <summary> /// Associates an arc with this circle. /// </summary> /// <param name="arc">The arc that coincides with the perimeter of this circle (must /// already be cross-referenced to this circle)</param> /// <exception cref="ArgumentException">If the specified arc does not already /// refer to this circle.</exception> internal void AddArc(ArcFeature arc) { if (arc.Circle != this) { throw new ArgumentException(); } if (!m_Arcs.Contains(arc)) { m_Arcs.Add(arc); } }
/// <summary> /// Creates a line feature that corresponds to one of the spans on this leg. /// Before calling this override, the circle object associated with this leg must /// be defined, via a call to <see cref="CreateCircle"/>. /// </summary> /// <param name="ff">The factory for creating new spatial features</param> /// <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 line (never null)</returns> /// <exception cref="InvalidOperationException">If the underlying circle for this leg has not /// been created via a prior call to <see cref="CreateCircle"/>.</exception> internal override LineFeature CreateLine(FeatureFactory ff, string itemName, PointFeature from, PointFeature to) { if (m_Circle == null) { throw new InvalidOperationException("Circle for circular arc has not been defined"); } ArcFeature result = ff.CreateArcFeature(itemName, from, to); // We have to create a geometry object at this stage, so that the circle can be // cross-referenced to created arcs. However, it's not fully defined because the // circle radius will likely be zero at this stage. result.Geometry = new ArcGeometry(m_Circle, from, to, m_Metrics.IsClockwise); return(result); }
/// <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 created feature (never null)</returns> internal virtual ArcFeature CreateArcFeature(string itemName, PointFeature from, PointFeature to) { ArcFeature result = null; IFeature f = FindFeatureDescription(itemName); if (f == null) { InternalIdValue id = MapModel.WorkingSession.AllocateNextId(); result = new ArcFeature(m_Operation, id, LineType, null, from, to, true); result.SetNextId(); } else { result = new ArcFeature(f, from, to, null, f.EntityType.IsPolygonBoundaryValid); } return(result); }
/// <summary> /// Ensures that a persistent field has been associated with a spatial feature. /// </summary> /// <param name="field">A tag associated with the item</param> /// <param name="feature">The feature to assign to the field (not null).</param> /// <returns> /// True if a matching field was processed. False if the field is not known to this /// class (may be known to another class in the type hierarchy). /// </returns> public bool ApplyFeatureRef(DataField field, Feature feature) { if (field == DataField.Center) { PointFeature center = (PointFeature)feature; m_Circle = new Circle(center, 0.0); center.AddReference(m_Circle); return(true); } if (field == DataField.FirstArc) { ArcFeature firstArc = (ArcFeature)feature; m_Circle = firstArc.Circle; return(true); } return(false); }
/// <summary> /// Checks whether this face is the face that caused the creation of a specific feature. /// </summary> /// <param name="feature">The feature to search for. The creator of this feature /// is expected to match the operation that contains this face. /// </param> /// <returns>True if this face caused the creation of the feature.</returns> internal bool IsCreatorOf(Feature feature) { foreach (SpanInfo sd in m_Spans) { // Skip if this was a null span. Feature f = sd.CreatedFeature; if (f == null) { continue; } // Return if we have a match. if (Object.ReferenceEquals(f, feature)) { return(true); } // If the feature is a line, also check any point feature at the end. LineFeature line = (f as LineFeature); if (line == null) { continue; } //const CePoint* pPoint = pArc->GetpEnd()->GetpPoint(*pop, onlyActive); PointFeature point = line.EndPoint; if (Object.ReferenceEquals(point, feature)) { return(true); } // If it's a circular arc, check the circle center point too. ArcFeature arc = (line as ArcFeature); if (arc != null && Object.ReferenceEquals(arc.Circle.CenterPoint, feature)) { return(true); } } return(false); }
private ArcFeature ImportArc(Ntx.Line line, Operation creator, ILength tol) { Debug.Assert(line.IsCurve); IEntity what = GetEntityType(line, SpatialType.Line); // Get positions defining the arc PointGeometry[] pts = GetPositions(line); // Ignore zero-length lines if (HasZeroLength(pts)) { return(null); } // Add a point at the center of the circle Ntx.Position pos = line.Center; PointGeometry pc = new PointGeometry(pos.Easting, pos.Northing); PointFeature center = EnsurePointExists(pc, tol, creator); // Calculate exact positions for the arc endpoints double radius = line.Radius; ICircleGeometry cg = new CircleGeometry(pc, radius); IPosition bc = CircleGeometry.GetClosestPosition(cg, pts[0]); IPosition ec = CircleGeometry.GetClosestPosition(cg, pts[pts.Length - 1]); // Round off to nearest micron PointGeometry bcg = PointGeometry.Create(bc); PointGeometry ecg = PointGeometry.Create(ec); // Ensure point features exist at both ends of the line. PointFeature ps = GetArcEndPoint(bcg, tol, creator); PointFeature pe = GetArcEndPoint(ecg, tol, creator); // Try to find a circle that's already been added by this import. Circle c = EnsureCircleExists(center, radius, tol, creator); // Determine which way the arc is directed bool iscw = LineStringGeometry.IsClockwise(pts, center); InternalIdValue id = CadastralMapModel.Current.WorkingSession.AllocateNextId(); ArcFeature arc = new ArcFeature(creator, id, what, c, ps, pe, iscw); // The toological status of the incoming arc may override the status that the // constructor derived from the entity type arc.SetTopology(line.IsTopologicalArc); #if DEBUG // Confirm the NTX data was valid (ensure it's consistent with what we've imported)... double readRad = c.Radius; double calcRad = BasicGeom.Distance(c.Center, ps); Debug.Assert(Math.Abs(readRad - calcRad) < tol.Meters); foreach (IPointGeometry pg in pts) { ILength check = arc.Geometry.Distance(pg); Debug.Assert(check.Meters < tol.Meters); } #endif return(arc); }
/// <summary> /// Removes an arc from this circle. This might be called if the operation that /// created the arc is getting rolled back. Another possible scenario is where /// the arc is being moved to coincide with a different circle. /// </summary> /// <param name="arc">The arc that no longer references this circle.</param> /// <returns>True if the specified arc was removed. False if it wasn't referenced.</returns> internal bool RemoveArc(ArcFeature arc) { return(m_Arcs.Remove(arc)); }
private ArcFeature ImportArc(Ntx.Line line, Operation creator, ILength tol) { Debug.Assert(line.IsCurve); IEntity what = GetEntityType(line, SpatialType.Line); // Get positions defining the arc PointGeometry[] pts = GetPositions(line); // Ignore zero-length lines if (HasZeroLength(pts)) return null; // Add a point at the center of the circle Ntx.Position pos = line.Center; PointGeometry pc = new PointGeometry(pos.Easting, pos.Northing); PointFeature center = EnsurePointExists(pc, tol, creator); // Calculate exact positions for the arc endpoints double radius = line.Radius; ICircleGeometry cg = new CircleGeometry(pc, radius); IPosition bc = CircleGeometry.GetClosestPosition(cg, pts[0]); IPosition ec = CircleGeometry.GetClosestPosition(cg, pts[pts.Length-1]); // Round off to nearest micron PointGeometry bcg = PointGeometry.Create(bc); PointGeometry ecg = PointGeometry.Create(ec); // Ensure point features exist at both ends of the line. PointFeature ps = GetArcEndPoint(bcg, tol, creator); PointFeature pe = GetArcEndPoint(ecg, tol, creator); // Try to find a circle that's already been added by this import. Circle c = EnsureCircleExists(center, radius, tol, creator); // Determine which way the arc is directed bool iscw = LineStringGeometry.IsClockwise(pts, center); InternalIdValue id = CadastralMapModel.Current.WorkingSession.AllocateNextId(); ArcFeature arc = new ArcFeature(creator, id, what, c, ps, pe, iscw); // The toological status of the incoming arc may override the status that the // constructor derived from the entity type arc.SetTopology(line.IsTopologicalArc); #if DEBUG // Confirm the NTX data was valid (ensure it's consistent with what we've imported)... double readRad = c.Radius; double calcRad = BasicGeom.Distance(c.Center, ps); Debug.Assert(Math.Abs(readRad-calcRad) < tol.Meters); foreach (IPointGeometry pg in pts) { ILength check = arc.Geometry.Distance(pg); Debug.Assert(check.Meters < tol.Meters); } #endif return arc; }