/// <summary> /// Checks if a divider is a dangle, floating, or a bridge. /// </summary> /// <param name="d">The divider to check</param> /// <returns>Bit mask of the check(s) the divider failed.</returns> static CheckType CheckNeighbours(IDivider d) { Debug.Assert(!d.IsOverlap); // Return if the divider has different polygons on both sides. if (d.Left != d.Right) { return(CheckType.Null); } bool sDangle = Topology.IsDangle(d, d.From); bool eDangle = Topology.IsDangle(d, d.To); if (sDangle && eDangle) { return(CheckType.Floating); } if (sDangle || eDangle) { return(CheckType.Dangle); } return(CheckType.Bridge); }
/// <summary> /// Gets the side code for a horizontal segment which is incident on a node, /// given any one the boundaries incident on the node. /// </summary> /// <param name="id">The divider we know about (incident on node).</param> /// <param name="isStart">True if it's the start of <c>ib</c>.</param> /// <param name="od">The divider the returned side refers to</param> /// <returns>Side.Left if the segment is to the left of <c>ob</c>, Side.Right /// if segment to the right.</returns> internal Side GetSide(IDivider id, bool isStart, out IDivider od) { ConnectionFinder connect = new ConnectionFinder(id, isStart, this); od = connect.Next; return(connect.IsStart ? Side.Right : Side.Left); }
/// <summary> /// Determines whether the sections in this list can be trimmed using the /// <see cref="TrimLineOperation"/> /// </summary> /// <returns>True if either end dangles, and we would be left with something /// after the trim.</returns> internal bool CanTrim() { // Can't trim if we don't have at least two sections if (m_Sections.Count < 2) { return(false); } // Get the sections at the ends. IDivider s = this.FirstDivider; IDivider e = this.LastDivider; Debug.Assert(s != e); // Return if neither end is dangling bool sDangle = Topology.IsDangle(s, s.From); bool eDangle = Topology.IsDangle(e, e.To); if (!(sDangle || eDangle)) { return(false); } // Can't process if both ends are dangling and the common point is coincident if (sDangle && eDangle && s.To.IsCoincident(e.From)) { return(false); } return(true); }
/// <summary> /// Performs checks on the supplied divider. /// </summary> /// <param name="d">The divider to check.</param> /// <returns>The problem(s) that were found.</returns> internal static CheckType Check(IDivider d) { // Ignore invisible dividers (the result of trimming dangling lines) if (!d.IsVisible) { return(CheckType.Null); } CheckType types = CheckType.Null; // Is the divider extremely small (smaller than 1mm on the mapping plane)? double len = d.LineGeometry.Length.Meters; if (len < 0.001) { types |= CheckType.SmallLine; } // Always flag overlaps. For all other dividers, check if // dangling, floating, or a bridge. if (d.IsOverlap) { types |= CheckType.Overlap; } else { types |= CheckNeighbours(d); } return(types); }
public ArithmeticCalculator(IAdder <T> adder, ISubtractor <T> subtractor, IMultiplier <T> multiplier, IDivider <T> divider) { _adder = adder; _subtractor = subtractor; _multiplier = multiplier; _divider = divider; }
/// <summary> /// Constructor used by <c>Ring.Create</c>. /// </summary> /// <param name="edge">The dividers that define the perimeter of the ring</param> protected Ring(RingMetrics metrics, List <Face> edge) : base(metrics) { m_Edge = new IDivider[edge.Count]; m_Flag = 0; for (int i = 0; i < m_Edge.Length; i++) { Face face = edge[i]; IDivider d = face.Divider; // Check for a divider that's already marked as being totally built. if (Topology.IsBuilt(d)) { throw new Exception("Polygon - Wrong build status for component divider"); } // Remember the divider and update polygon geometry m_Edge[i] = d; if (face.IsLeft) { d.Left = this; } else { d.Right = this; } } }
/// <summary> /// Creates a new <c>RingMetrics</c> object for the supplied faces. /// </summary> /// <param name="edge">The faces defining a ring</param> internal RingMetrics(List <Face> edge) { m_Area = 0.0; m_Window = new Window(); foreach (Face face in edge) { IDivider d = face.Divider; bool isLeft = face.IsLeft; double area, length; IWindow awin; d.LineGeometry.GetGeometry(out awin, out area, out length); m_Window.Union(awin); if (face.IsLeft) { m_Area -= area; } else { m_Area += area; } } }
public Calculator(IQueryParser queryParser, IMultiplier multipler, IAdder adder, ISubtractor subtractor, IDivider divider) { _queryParser = queryParser; _multiplier = multipler; _adder = adder; _subtractor = subtractor; _divider = divider; }
/// <summary> /// Creates a new <c>DividerObject</c> that wraps the supplied divider. /// </summary> /// <param name="d">The divider to wrap</param> internal DividerObject(IDivider d) { if (d==null) throw new ArgumentNullException(); m_Divider = d; m_Geom = m_Divider.LineGeometry; }
/// <summary> /// Default constructor /// </summary> internal PolygonFace() { m_Polygon = null; m_Divider = null; m_Begin = null; m_End = null; m_ExtraPoints = null; }
public Calculator(IAdder adder, ISubtractor subtractor, IDivider divider, IMultiplier multiplier, IExponenter exponenter) { this.adder = adder; this.subtractor = subtractor; this.divider = divider; this.multiplier = multiplier; this.exponenter = exponenter; }
/// <summary> /// Creates a new <c>DividerCheck</c> that relates to the specified divider. /// </summary> /// <param name="divider">The divider the check relates to (not null).</param> /// <param name="types">The type(s) of check this item corresponds to</param> /// <exception cref="ArgumentNullException">If <paramref name="divider"/> is null</exception> internal DividerCheck(IDivider divider, CheckType types) : base(types) { if (divider==null) throw new ArgumentNullException(); m_Divider = divider; }
// .cctor static DivideManager() { // Create new classic divider instance IDivider classicDivider = new ClassicDivider(); // Fill publicity visible divider fields ClassicDivider = classicDivider; AutoNewtonDivider = new AutoNewtonDivider(classicDivider); }
public Decomposed Execute( Factor factors, IDivider divider, dynamic algorithm, IUserAlgorithmStrategyProvider strategtProvider ) { factors = Normalize(factors); var decomposed = new Decomposed(); decomposed.Factors.Add(factors); var continueFlag = true; while (continueFlag) { continueFlag = false; var freeTermFactors = (List <int>)GetNumberFactors(decomposed.Factors.Last().Terms.Where(x => x.SymbolsPower == 0).Select(term => term.Number).FirstOrDefault(), algorithm, strategtProvider ); freeTermFactors.ForEach(coefficent => { var dividedPart = divider.Divide(decomposed.Factors.Last(), -coefficent); if (dividedPart != null) { Console.WriteLine(decomposed); var newdividerFactor = new Factor(); newdividerFactor.Terms = new List <Term>() { new Term { Number = 1, Sign = Sign.Plus, Symbol = 'x', SymbolsPower = 1 }, new Term { Number = Math.Abs(coefficent), Sign = (coefficent >= 0) ? Sign.Minus : Sign.Plus, SymbolsPower = 1 } }; decomposed.Factors.Insert(0, newdividerFactor); decomposed.Factors[decomposed.Factors.Count() - 1] = dividedPart; continueFlag = true; } }); } return(decomposed); }
/// <summary> /// Creates a new <c>DividerCheck</c> that relates to the specified divider. /// </summary> /// <param name="divider">The divider the check relates to (not null).</param> /// <param name="types">The type(s) of check this item corresponds to</param> /// <exception cref="ArgumentNullException">If <paramref name="divider"/> is null</exception> internal DividerCheck(IDivider divider, CheckType types) : base(types) { if (divider == null) { throw new ArgumentNullException(); } m_Divider = divider; }
/// <summary> /// Creates a new <c>DividerObject</c> that wraps the supplied divider. /// </summary> /// <param name="d">The divider to wrap</param> internal DividerObject(IDivider d) { if (d == null) { throw new ArgumentNullException(); } m_Divider = d; m_Geom = m_Divider.LineGeometry; }
/// <summary> /// This function loops through the items of the collection of values and performs the division or attemps to divide. /// The result returned will be displayed by the print delegate, which is set by the caller. /// </summary> /// <param name="divider"></param> /// <param name="print"></param> public void RunDivider(IDivider divider, Delegates.DisplayDelegate display) { string returnResult; display("There are " + _nObjects.Count() + " elements in the collection."); foreach (NObject nObject in _nObjects) { returnResult = divider.Divide(nObject); display(returnResult); } }
public IDivider[] IncidentDividers() { List <IDivider> result = new List <IDivider>(4); // 4 is frequently the number in the result foreach (IFeatureDependent fd in Dependents) { if (fd is LineFeature) { LineFeature line = (fd as LineFeature); Topology t = line.Topology; if (t != null) { // Could have a situation where BOTH start and end of the line end // at the same point (e.g. a multisegment that loops back on itself). bool sMatch = line.StartPoint.IsCoincident(this); bool eMatch = line.EndPoint.IsCoincident(this); if (sMatch) { IDivider d = t.FirstDivider; if (!d.IsOverlap) { result.Add(d); } } if (eMatch) { // The result could conceivably contain the divider already (case where a multi-segment // closes on itself) IDivider d = t.LastDivider; if (!d.IsOverlap && !result.Contains(d)) { result.Add(d); } } if (!(sMatch || eMatch)) { // Cover a situation where this point is referenced to a line that // passes through (intersection). Debug.Assert(t is SectionTopologyList); SectionTopologyList sections = (t as SectionTopologyList); sections.AddIncidentDividers(result, this); } } } } return(result.ToArray()); }
/// <summary> /// Replaces topology associated with this instance. This gets called when the /// topology is getting cut up at intersections. /// </summary> /// <param name="oldDivider">The divider that's being replaced</param> /// <param name="newDividers">The dividers to insert in place of <paramref name="oldDivider"/></param> /// <exception cref="ArgumentException">If <paramref name="oldDivider"/> is not /// part of this list</exception> internal void ReplaceDivider(IDivider oldDivider, List <IDivider> newDividers) { int index = m_Sections.IndexOf(oldDivider); if (index < 0) { throw new ArgumentException("SectionTopologyList.ReplaceDivider - Cannot locate topological section"); } m_Sections.RemoveAt(index); m_Sections.InsertRange(index, newDividers); }
/// <summary> /// One-time definition of the topological divider that this face corresponds to. /// </summary> /// <param name="pol">The polygon this face is part of</param> /// <param name="line">The topological line that acts as the primary face for /// some portion of the polygon boundary</param> /// <returns>The number of points for this face (one for the start of the face, /// plus any intermediate points along the face).</returns> internal uint SetDivider(Polygon pol, IDivider line) { // Expect that this method should only ever get called once in the // lifetime of an instance Debug.Assert(m_ExtraPoints == null); // Define any extra points m_Polygon = pol; m_Divider = line; int nExtra = SetExtraPoints(); return((uint)(1 + nExtra)); }
/// <summary> /// Will a divider associated with this topology be drawn by the <see cref="RenderTrimmed"/> /// method? /// </summary> /// <param name="d">One of the dividers in this list</param> /// <returns>True if the divider coincides with a dangling portion of the line.</returns> internal bool IsVisible(IDivider d) { if (Object.ReferenceEquals(d, FirstDivider)) { return(!Line.IsStartDangle()); } if (Object.ReferenceEquals(d, LastDivider)) { return(!Line.IsEndDangle()); } return(true); }
/// <summary> /// Creates new <c>Orientation</c> for one end of a divider /// </summary> /// <param name="d">The divider we are interested in (not null)</param> /// <param name="isStart">At start of the divider?</param> /// <exception cref="ArgumentNullException">If <paramref name="d"/> is null</exception> internal Orientation(IDivider d, bool isStart) { if (d==null) throw new ArgumentNullException("Divider cannot be null"); m_Divider = d; m_IsStart = isStart; // Get orientation point for the divider IPosition orient = d.LineGeometry.GetOrient(isStart, 0.0); // Set the orientation info. SetOrient(orient); }
/// <summary> /// Checks whether this selection refers to the same spatial objects as /// another selection, and has the same reference position. /// </summary> /// <param name="that">The selection to compare with</param> /// <returns>True if the two selections refer to the same spatial objects (not /// necessarily in the same order)</returns> public bool Equals(ISpatialSelection that) { // The same spatial objects have to be involved if (!SpatialSelection.Equals(this, that)) return false; // If both selections refer to the same divider (or null), they're the same Selection other = (that as Selection); if (other == null) return false; IDivider d1 = (this.m_Section == null ? null : this.m_Section.Divider); IDivider d2 = (other.m_Section == null ? null : other.m_Section.Divider); return Object.ReferenceEquals(d1, d2); }
/// <summary> /// Creates new <c>Orientation</c> for one end of a divider /// </summary> /// <param name="d">The divider we are interested in (not null)</param> /// <param name="isStart">At start of the divider?</param> /// <exception cref="ArgumentNullException">If <paramref name="d"/> is null</exception> internal Orientation(IDivider d, bool isStart) { if (d == null) { throw new ArgumentNullException("Divider cannot be null"); } m_Divider = d; m_IsStart = isStart; // Get orientation point for the divider IPosition orient = d.LineGeometry.GetOrient(isStart, 0.0); // Set the orientation info. SetOrient(orient); }
/// <summary> /// Returns the name of a derived entity type associated with a line. /// If an entity file has been loaded, this may be based on the entity /// types of the adjacent polygons. Failing that, the result will be /// the same as the name of the line's "normal" entity type. /// </summary> /// <param name="line">The line to process.</param> /// <param name="layer">The layer of interest.</param> /// <returns>The name of the derived entity type (may be blank)</returns> internal static string GetDerivedType(IDivider line, ILayer layer) { // If we have an entity file, and it can return a derived type, // that's us done. if (s_EntityFile != null) { string dervEntName = s_EntityFile.GetDerivedType(line, layer); if (dervEntName != null) { return(dervEntName); } } // Get the line's entity type (if any). IEntity lineEnt = line.Line.EntityType; return(lineEnt == null ? String.Empty : lineEnt.Name); }
/// <summary> /// Merges divider sections that are incident on the specified intersection. This gets /// called when one of the lines causing an intersection is being removed (deactivated). /// </summary> /// <param name="x">An intersection that is being removed</param> /// <returns>The number of sections after the merge</returns> internal override int MergeSections(Intersection x) { for (int i = 0; i < (m_Sections.Count - 1); i++) { IDivider a = m_Sections[i]; if (a.To == x) { IDivider b = m_Sections[i + 1]; // If either divider is an overlap, it would be BAD to merge if (a is SectionDivider && b is SectionDivider) { m_Sections.RemoveAt(i + 1); m_Sections[i] = new SectionDivider(Line, a.From, b.To); } } } return(m_Sections.Count); }
/// <summary> /// Creates new <c>Orientation</c> based on the supplied horizontal ray. /// </summary> /// <param name="hr"></param> internal Orientation(HorizontalRay hr) { // Remember the stuff we were supplied (since we are not starting // with a divider, it has to be null). m_Divider = null; m_IsStart = false; // The horizontal segment is ALWAYS at the very start of the // north-west quadrant. m_Quadrant = Quadrant.NW; // Convert the deltas into the IJ coordinate system for the // north-west quadrant (the angle defined with I/J should // evaluate to zero, since the horizontal segment is at the // start of the quadrant). m_DeltaI = 0.0; m_DeltaJ = hr.EndX - hr.StartX; }
/// <summary> /// Returns the style for the specified line /// </summary> /// <param name="line">The feature to get the style for</param> /// <param name="layer">The editing layer</param> /// <returns>The corresponding style (never null)</returns> internal static Style GetStyle(IDivider line, ILayer layer) { if (s_StyleFile == null) { return(s_BlackStyle); } // Get the name of the (possibly derived) entity type string entName = GetDerivedType(line, layer); // Nothing at all means we should have a construction // line, which is always symbolized as a black dotted line. if (entName.Length == 0) { return(s_BlackDottedLineStyle); } // Try to get a style using the name of the derived // entity type. Style style = s_StyleFile.GetStyle(entName); if (style != null) { return(style); } /* * // If we didn't get anything, look for a style that * // refers to the line's base theme. * ILayer t = line.Line.BaseLayer; * if (t != null) * { * style = s_StyleFile.GetStyle(t.Name); * if (style != null) * return style; * } */ // Return the default style return(s_BlackStyle); }
/// <summary> /// Tries to return the name of a derived entity type for a specific line. /// </summary> /// <param name="line">The line to process.</param> /// <param name="layer">The layer of interest (in the same address space as /// the map that contains the line).</param> /// <returns>The name of the derived entity type (null if not found).</returns> internal string GetDerivedType(IDivider line, ILayer layer) { // Return if the line does not have an entity type (it SHOULD do) IEntity ent = line.Line.EntityType; if (ent == null) { return(null); } // Get the translation block (if any) that refers to the line's entity type. string entName = ent.Name; string lyrName = layer.Name; EntityBlock block = Array.Find <EntityBlock>(m_Blocks, eb => eb.IsMatch(entName, lyrName)); // Return if the line's entity type is not associated with a translation. if (block == null) { return(null); } // Get the polygons on either side of the line (the REAL // user-perceived polygons, not phantoms). Polygon leftPol = (line.Left == null ? null : line.Left.RealPolygon); Polygon rightPol = (line.Right == null ? null : line.Right.RealPolygon); // Get the entity types for the adjacent polygons (if any). IEntity leftEnt = (leftPol == null ? null : leftPol.EntityType); IEntity rightEnt = (rightPol == null ? null : rightPol.EntityType); if (leftEnt != null || rightEnt != null) { string e1 = (leftEnt == null ? String.Empty : leftEnt.Name); string e2 = (rightEnt == null ? String.Empty : rightEnt.Name); return(block.GetDerivedType(e1, e2)); } return(null); }
/// <summary> /// Locates the divider that is closest to the specified position. /// </summary> /// <param name="p">The position of interest</param> /// <returns>The closest section (null if there are no sections in this list)</returns> internal IDivider FindClosestSection(IPosition p) { if (m_Sections.Count == 0) { return(null); } IDivider result = m_Sections[0]; double minDist = result.LineGeometry.Distance(p).Meters; for (int i = 1; i < m_Sections.Count; i++) { double d = m_Sections[i].LineGeometry.Distance(p).Meters; if (d < minDist) { minDist = d; result = m_Sections[i]; } } return(result); }
/// <summary> /// Creates a new <c>Selection</c> that contains a single item (or nothing). /// </summary> /// <param name="so">The object to remember as part of this selection (if null, it /// will not be added to the selection)</param> /// <param name="searchPosition">A position associated with the selection (null /// if a specific position isn't relevant). This is used to determine whether a /// topological section is relevant when a line is selected.</param> public Selection(ISpatialObject so, IPosition searchPosition) { m_Items = new List<ISpatialObject>(1); if (so!=null) m_Items.Add(so); // If we're dealing with a single line that's been topologically sectioned, // determine which divider we're closest to. m_Section = null; if (searchPosition != null) { LineFeature line = (so as LineFeature); if (line != null && line.Topology is SectionTopologyList) { SectionTopologyList sections = (line.Topology as SectionTopologyList); IDivider d = sections.FindClosestSection(searchPosition); if (d != null) m_Section = new DividerObject(d); } } }
/// <summary> /// Draws sections on the specified display, excluding dangling ends. /// </summary> /// <param name="display">The display to draw to</param> /// <param name="style">The drawing style</param> internal void RenderTrimmed(ISpatialDisplay display, IDrawStyle style) { // If we're highlighting, dangling portions should be drawn dotted IDrawStyle dangleStyle = (style is HighlightStyle ? new DottedStyle(Color.Red) : null); bool sDangle = Line.IsStartDangle(); bool eDangle = Line.IsEndDangle(); int last = m_Sections.Count - 1; for (int i = 0; i <= last; i++) { if ((i == 0 && !sDangle) || (i > 0 && i < last) || (i == last && !eDangle)) { IDivider d = m_Sections[i]; d.Line.RenderDivider(d, display, style); } else if (dangleStyle != null && ((i == 0 && sDangle) || (i == last && eDangle))) { IDivider d = m_Sections[i]; d.Line.RenderDivider(d, display, dangleStyle); } } }
/// <summary> /// Performs checks on the supplied divider. /// </summary> /// <param name="d">The divider to check.</param> /// <returns>The problem(s) that were found.</returns> internal static CheckType Check(IDivider d) { // Ignore invisible dividers (the result of trimming dangling lines) if (!d.IsVisible) return CheckType.Null; CheckType types = CheckType.Null; // Is the divider extremely small (smaller than 1mm on the mapping plane)? double len = d.LineGeometry.Length.Meters; if (len < 0.001) types |= CheckType.SmallLine; // Always flag overlaps. For all other dividers, check if // dangling, floating, or a bridge. if (d.IsOverlap) types |= CheckType.Overlap; else types |= CheckNeighbours(d); return types; }
/// <summary> /// Checks if a divider is a dangle, floating, or a bridge. /// </summary> /// <param name="d">The divider to check</param> /// <returns>Bit mask of the check(s) the divider failed.</returns> static CheckType CheckNeighbours(IDivider d) { Debug.Assert(!d.IsOverlap); // Return if the divider has different polygons on both sides. if (d.Left != d.Right) return CheckType.Null; bool sDangle = Topology.IsDangle(d, d.From); bool eDangle = Topology.IsDangle(d, d.To); if (sDangle && eDangle) return CheckType.Floating; if (sDangle || eDangle) return CheckType.Dangle; return CheckType.Bridge; }
/// <summary> /// Is a divider associated with this line visible? /// </summary> /// <param name="d">One of the dividers associated with the topology for this line</param> /// <returns>False if this line is marked as trimmed, and the specified divider is not /// currently drawn.</returns> internal bool IsVisible(IDivider d) { // The logic here should mimic that of RenderTopologicalLine above. if (IsTrimmed && (m_Topology is SectionTopologyList)) return (m_Topology as SectionTopologyList).IsVisible(d); else return true; }
/// <summary> /// Returns the style for the specified line /// </summary> /// <param name="line">The feature to get the style for</param> /// <param name="layer">The editing layer</param> /// <returns>The corresponding style (never null)</returns> internal static Style GetStyle(IDivider line, ILayer layer) { if (s_StyleFile == null) return s_BlackStyle; // Get the name of the (possibly derived) entity type string entName = GetDerivedType(line, layer); // Nothing at all means we should have a construction // line, which is always symbolized as a black dotted line. if (entName.Length == 0) return s_BlackDottedLineStyle; // Try to get a style using the name of the derived // entity type. Style style = s_StyleFile.GetStyle(entName); if (style != null) return style; /* // If we didn't get anything, look for a style that // refers to the line's base theme. ILayer t = line.Line.BaseLayer; if (t != null) { style = s_StyleFile.GetStyle(t.Name); if (style != null) return style; } */ // Return the default style return s_BlackStyle; }
/// <summary> /// Returns the name of a derived entity type associated with a line. /// If an entity file has been loaded, this may be based on the entity /// types of the adjacent polygons. Failing that, the result will be /// the same as the name of the line's "normal" entity type. /// </summary> /// <param name="line">The line to process.</param> /// <param name="layer">The layer of interest.</param> /// <returns>The name of the derived entity type (may be blank)</returns> internal static string GetDerivedType(IDivider line, ILayer layer) { // If we have an entity file, and it can return a derived type, // that's us done. if (s_EntityFile != null) { string dervEntName = s_EntityFile.GetDerivedType(line, layer); if (dervEntName != null) return dervEntName; } // Get the line's entity type (if any). IEntity lineEnt = line.Line.EntityType; return (lineEnt == null ? String.Empty : lineEnt.Name); }
/// <summary> /// Replaces topology associated with this instance. This gets called when the /// topology is getting cut up at intersections. /// </summary> /// <param name="oldDivider">The divider that's being replaced</param> /// <param name="newDividers">The dividers to insert in place of <paramref name="oldDivider"/></param> /// <exception cref="ArgumentException">If <paramref name="oldDivider"/> is not /// part of this list</exception> internal void ReplaceDivider(IDivider oldDivider, List<IDivider> newDividers) { int index = m_Sections.IndexOf(oldDivider); if (index<0) throw new ArgumentException("SectionTopologyList.ReplaceDivider - Cannot locate topological section"); m_Sections.RemoveAt(index); m_Sections.InsertRange(index, newDividers); }
/// <summary> /// Will a divider associated with this topology be drawn by the <see cref="RenderTrimmed"/> /// method? /// </summary> /// <param name="d">One of the dividers in this list</param> /// <returns>True if the divider coincides with a dangling portion of the line.</returns> internal bool IsVisible(IDivider d) { if (Object.ReferenceEquals(d, FirstDivider)) return !Line.IsStartDangle(); if (Object.ReferenceEquals(d, LastDivider)) return !Line.IsEndDangle(); return true; }
/// <summary> /// Cuts up a divider that covers this line (or a portion of this line) /// </summary> /// <param name="arePolygonsBuilt">Has polygon topology been built (false if the split /// is being done as part of the initial load).</param> /// <param name="div">The divider covering the line (or a portion of this line)</param> /// <param name="xres">The places where intersections have been detected on /// the divider</param> /// <param name="retrims">Lines that need to be re-trimmed (the line associated /// with the divider will be appended if an intersection is made on an invisible /// portion of the divider). Not currently used.</param> void Cut(bool arePolygonsBuilt, IDivider div, IntersectionResult xres, List<LineFeature> retrims) { Debug.Assert(div.Line == this); // Should never need to cut anything that represents an overlap (they're // supposed to be treated as non-topological) Debug.Assert(!div.IsOverlap); // Return if nothing to do List<IntersectionData> data = xres.Intersections; if (data == null || data.Count == 0) return; // Ensure that any polygons known to this boundary have been // marked for deletion (need to do this in case the intersects // we have are only at the line end points, in which case we // wouldn't actually change anything). if (arePolygonsBuilt) Topology.MarkPolygons(div); // We'll need the map for creating intersection points CadastralMapModel map = CadastralMapModel.Current; // Create list of resultant sections List<IDivider> result = new List<IDivider>(); ITerminal from, to; from = to = div.From; for (int i = 0; i < data.Count; i++, from = to) { // Get the intersection data. IntersectionData x = data[i]; if (x.IsGraze) { // There are 4 sorts of graze to deal with: // 1. The graze covers the complete line. // 2. The graze is at the start of the line. // 3. The graze is along some interior portion of the line. // 4. The graze is at the end of the line. // If it's a total graze, there should only be ONE intersection. if (x.IsTotalGraze) { Debug.Assert(data.Count == 1); if (data.Count != 1) throw new Exception("LineFeature.Cut - Multiple overlaps detected"); // Mark all polygons incident on the terminals. Topology.MarkPolygons(div.From); Topology.MarkPolygons(div.To); // Define overlap for the entire divider if (div is LineTopology) result.Add(new LineOverlap(div.Line)); else result.Add(new SectionOverlap(this, div.From, div.To)); to = div.To; } else if (x.IsStartGraze) { Debug.Assert(i == 0); Debug.Assert(from == div.From); // Mark all polygons incident at the start terminal if (arePolygonsBuilt) Topology.MarkPolygons(div.From); // Create an overlap at the start of this divider to = map.GetTerminal(x.P2); if (from != to) result.Add(new SectionOverlap(this, from, to)); } else if (x.IsInteriorGraze) { // Add a section from the current tail to the start of the graze // 05-APR-2003 (somehow got a simple x-sect followed by a graze, so ensure we don't add a null section) to = map.GetTerminal(x.P1); if (from != to) result.Add(new SectionDivider(this, from, to)); // Add the overlap from = to; to = map.GetTerminal(x.P2); if (from != to) result.Add(new SectionOverlap(this, from, to)); } else if (x.IsEndGraze) { // Mark all polygons incident on the end terminal if (arePolygonsBuilt) Topology.MarkPolygons(div.To); // Add a topological section up to the start of the graze to = map.GetTerminal(x.P1); if (from != to) result.Add(new SectionDivider(this, from, to)); // Add overlap all the way to the end of this divider from = to; to = div.To; if (from != to) result.Add(new SectionOverlap(this, from, to)); // That should be the LAST cut. Debug.Assert((i + 1) == data.Count); } else { throw new Exception("LineFeature.Cut - Unexpected graze"); } } else if (!x.IsEnd) { // If the intersection is not at either end of the // divider, make a split (both portions topological). to = map.GetTerminal(x.P1); if (from != to) result.Add(new SectionDivider(this, from, to)); } } // Add the last section if we're not already at the end (we'll be at the end if // an overlap ran to the end) from = to; to = div.To; if (from != to) { // Just return if the terminals correspond to the two ends of this line. This // is intended to cover the case where we have a single interesection at the // start or end of the line. if (from.IsCoincident(StartPoint) && to.IsCoincident(EndPoint)) { Debug.Assert(result.Count==0); return; } result.Add(new SectionDivider(this, from, to)); } // Refer the associated line to the new sections if (result.Count > 0) { if (m_Topology is LineTopology) m_Topology = new SectionTopologyList(this, result); else { SectionTopologyList container = (SectionTopologyList)m_Topology; container.ReplaceDivider(div, result); } } }
/// <summary> /// One-time definition of the topological divider that this face corresponds to. /// </summary> /// <param name="pol">The polygon this face is part of</param> /// <param name="line">The topological line that acts as the primary face for /// some portion of the polygon boundary</param> /// <returns>The number of points for this face (one for the start of the face, /// plus any intermediate points along the face).</returns> internal uint SetDivider(Polygon pol, IDivider line) { // Expect that this method should only ever get called once in the // lifetime of an instance Debug.Assert(m_ExtraPoints==null); // Define any extra points m_Polygon = pol; m_Divider = line; int nExtra = SetExtraPoints(); return (uint)(1+nExtra); }
IDivider _classicDivider; // divider to use if Newton approach is unapplicatible #endregion Private fields #region Constructor /// <summary> /// Creates new <see cref="AutoNewtonDivider" /> instance. /// </summary> /// <param name="classicDivider">Divider to use if Newton approach is unapplicatible.</param> public AutoNewtonDivider(IDivider classicDivider) { _classicDivider = classicDivider; }
IDivider _classicDivider; // divider to use if Newton approach is unapplicatible #endregion Fields #region Constructors /// <summary> /// Creates new <see cref="AutoNewtonDivider" /> instance. /// </summary> /// <param name="classicDivider">Divider to use if Newton approach is unapplicatible.</param> public AutoNewtonDivider(IDivider classicDivider) { _classicDivider = classicDivider; }
/// <summary> /// Tries to return the name of a derived entity type for a specific line. /// </summary> /// <param name="line">The line to process.</param> /// <param name="layer">The layer of interest (in the same address space as /// the map that contains the line).</param> /// <returns>The name of the derived entity type (null if not found).</returns> internal string GetDerivedType(IDivider line, ILayer layer) { // Return if the line does not have an entity type (it SHOULD do) IEntity ent = line.Line.EntityType; if (ent==null) return null; // Get the translation block (if any) that refers to the line's entity type. string entName = ent.Name; string lyrName = layer.Name; EntityBlock block = Array.Find<EntityBlock>(m_Blocks, eb => eb.IsMatch(entName, lyrName)); // Return if the line's entity type is not associated with a translation. if (block==null) return null; // Get the polygons on either side of the line (the REAL // user-perceived polygons, not phantoms). Polygon leftPol = (line.Left==null ? null : line.Left.RealPolygon); Polygon rightPol = (line.Right==null ? null : line.Right.RealPolygon); // Get the entity types for the adjacent polygons (if any). IEntity leftEnt = (leftPol==null ? null : leftPol.EntityType); IEntity rightEnt = (rightPol==null ? null : rightPol.EntityType); if (leftEnt!=null || rightEnt!=null) { string e1 = (leftEnt==null ? String.Empty : leftEnt.Name); string e2 = (rightEnt==null ? String.Empty : rightEnt.Name); return block.GetDerivedType(e1, e2); } return null; }
/// <summary> /// Gets the side code for a horizontal segment which is incident on a node, /// given any one the boundaries incident on the node. /// </summary> /// <param name="id">The divider we know about (incident on node).</param> /// <param name="isStart">True if it's the start of <c>ib</c>.</param> /// <param name="od">The divider the returned side refers to</param> /// <returns>Side.Left if the segment is to the left of <c>ob</c>, Side.Right /// if segment to the right.</returns> internal Side GetSide(IDivider id, bool isStart, out IDivider od) { ConnectionFinder connect = new ConnectionFinder(id, isStart, this); od = connect.Next; return (connect.IsStart ? Side.Right : Side.Left); }
/// <summary> /// Draws a portion of this topological line on the specified display /// </summary> /// <param name="d">The divider that corresponds to a portion of this line (could /// be the entire line)</param> /// <param name="display">The display to draw to</param> /// <param name="style">The drawing style</param> internal void RenderDivider(IDivider d, ISpatialDisplay display, IDrawStyle style) { // If we're highlightling, don't attempt to pick up any other display color if (style is HighlightStyle || style.IsFixed) { d.LineGeometry.Render(display, style); return; } Style s = EntityUtil.GetStyle(d, EditingController.Current.ActiveLayer); Pen oldPen = style.Pen; try { ScaleSpecificPen ssPen = s.GetPen(display); style.Pen = ssPen.Pen; d.LineGeometry.Render(display, style); } finally { style.Pen = oldPen; } }