/// <summary> /// Constructor used to combine a series of <c>IntersectResult</c> objects. This /// implementation is used to obtain a results object for a new topological line /// that has just been intersected against the map. /// </summary> /// <param name="xsect">The result of intersecting a line with the map</param> internal IntersectionResult(IntersectionFinder xsect) { m_IntersectedObject = xsect.Intersector; m_Geom = m_IntersectedObject.LineGeometry; m_Data = null; // Get the total number of intersections that were found (there's one // InteresectionResult for each intersected line) IList<IntersectionResult> results = xsect.Intersections; int nData = 0; foreach (IntersectionResult r in results) nData += r.m_Data.Count; // Return if no intersections. if (nData==0) return; // Copy over the info m_Data = new List<IntersectionData>(nData); foreach (IntersectionResult r in results) { List<IntersectionData> data = r.Intersections; foreach (IntersectionData d in data) m_Data.Add(d); } // Reverse all context codes. foreach (IntersectionData d in m_Data) d.ReverseContext(); }
/// <summary> /// Confirms that a potential link is valid. For a link to be valid, the /// midpoint of the link must fall inside the specified polygon, and the /// line connecting the 2 points cannot intersect anything. /// </summary> /// <param name="other">The end of the proposed point to link to.</param> /// <param name="pol">The polygon the link must fall completely inside.</param> /// <returns>True if link is valid.</returns> internal bool IsLinkValid(PolygonLink other, Polygon pol) { // 22-MAR-00 There may be no point at a corner. if (m_Point == null || other.Point == null) { return(false); } // Get the midpoint of the link. IPosition mid = Geom.MidPoint(m_Point, other.Point); // Confirm the midpoint falls inside the right polygon. if (!pol.IsRingEnclosing(mid)) { return(false); } // Locate any intersections formed by the proposed link (considering // only the currently active theme). LineGeometry seg = new SegmentGeometry(m_Point, other.m_Point); IntersectionFinder xsect = new IntersectionFinder(seg, true); // The proposed link is not valid if it intersects anything // along the length of the segment, or has any grazes. if (xsect.IsGrazing || xsect.IsSplitNeeded) { return(false); } return(true); }
/// <summary> /// Updates info on the longest horizontal span that crosses this polygon (used /// by <see cref="GetLabelPosition"/>) /// </summary> /// <param name="y">The Y-value of the scan line.</param> /// <param name="minx">The X-value for the western end of the scan line.</param> /// <param name="maxx">The X-value for the eastern end of the scan line.</param> /// <param name="weight">Weighting factor to use when comparing span lengths versus /// the initial best length.</param> /// <param name="beststart">The position of the start of the best span.</param> /// <param name="bestend">The position of the end of the best span.</param> /// <param name="bestlen">The weighted length of the best span. This is what defines /// the meaning of "best".</param> void GetLabelSpan(double y, double minx, double maxx, double weight, ref IPosition beststart, ref IPosition bestend, ref double bestlen) { // Define scan line. ITerminal sloc = new FloatingTerminal(minx, y); ITerminal eloc = new FloatingTerminal(maxx, y); SegmentGeometry seg = new SegmentGeometry(sloc, eloc); // Intersect with the map IntersectionFinder xseg = new IntersectionFinder(seg, true); // Arrange intersections along the scan line. IntersectionResult xres = new IntersectionResult(xseg); xres.Sort(true); // Define start of the first span IPosition start = sloc; IPosition end = null; // Go through each successive intersection, to locate spans // that run through the interior of the polygon. foreach (IntersectionData d in xres.Intersections) { // If the intersection is a graze if (d.IsGraze) { // Just define the end of the graze as the end point (there's // no point in trying to locate a label along the graze). end = d.P2; } else { // Simple intersection... // Get the next intersection end = d.P1; // Get the midpoint of the span. IPosition mid = Position.CreateMidpoint(start, end); // If the midpoint really falls inside this polygon, see whether the span // length is bigger than what we already have (if anything). if (this.IsEnclosing(mid)) { double len = (end.X - start.X) / weight; if (len > bestlen) { bestlen = len; beststart = start; bestend = end; } } } start = end; } }
/// <summary> /// Constructor used to combine a series of <c>IntersectResult</c> objects. This /// implementation is used to obtain a results object for a new topological line /// that has just been intersected against the map. /// </summary> /// <param name="xsect">The result of intersecting a line with the map</param> internal IntersectionResult(IntersectionFinder xsect) { m_IntersectedObject = xsect.Intersector; m_Geom = m_IntersectedObject.LineGeometry; m_Data = null; // Get the total number of intersections that were found (there's one // InteresectionResult for each intersected line) IList <IntersectionResult> results = xsect.Intersections; int nData = 0; foreach (IntersectionResult r in results) { nData += r.m_Data.Count; } // Return if no intersections. if (nData == 0) { return; } // Copy over the info m_Data = new List <IntersectionData>(nData); foreach (IntersectionResult r in results) { List <IntersectionData> data = r.Intersections; foreach (IntersectionData d in data) { m_Data.Add(d); } } // Reverse all context codes. foreach (IntersectionData d in m_Data) { d.ReverseContext(); } }
/// <summary> /// Do any splits needed upon addition of a new 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="retrims">Intersecting lines that were split on the invisible /// portion of a trimmed line. The lines in this list will need to be re-trimmed. /// </param> /// <remarks> /// 15-NOV-99: This function used to be called all over the place. It should now /// be called ONLY by <see cref="CadastralMapModel.Intersect"/>. To indicate that /// a line needs to be intersected, set the <see cref="IsMoved"/> property to /// true. /// </remarks> internal void Split(bool arePolygonsBuilt, List<LineFeature> retrims) { // No need to split lines that aren't topological. if (!IsTopological) return; if (m_Topology==null) throw new Exception("LineFeature.Split - topology hasn't been initialized"); // This method should only be called for complete lines (with no pre-existing // topological sections) if (!(m_Topology is LineTopology)) { string msg = String.Format("LineFeature.Split - Line {0} is associated with the wrong type of topology ({1})", InternalId, m_Topology.GetType().Name); throw new Exception(msg); } LineTopology lineTop = (LineTopology)m_Topology; // Intersect this line with the map (ignoring end to end intersects). IntersectionFinder xf = new IntersectionFinder(this, false); // Return if no intersections. IList<IntersectionResult> intersectedDividers = xf.Intersections; if (intersectedDividers.Count==0) return; // Cut up the things that were intersected, making grazing portions non-topological. // Each result object should be associated with an IDivider. foreach (IntersectionResult r in intersectedDividers) Cut(arePolygonsBuilt, r, retrims); // Combine the results and get the splitter to cut itself up. IntersectionResult xres = new IntersectionResult(xf); if (arePolygonsBuilt) { // If there is a graze at the start of this line, ensure // that all polygons incident on the start location have // been marked for deletion. Same for the end. if (xres.IsStartGrazing) Topology.MarkPolygons(StartPoint); if (xres.IsEndGrazing) Topology.MarkPolygons(EndPoint); } // Modify the intersection results so that the exit point // of each graze will be treated as a simple intersection. // While at it, ensure there are no duplicates, and ensure // we don't have any intersections at the end of the line. if (xres.Simplify()==0) return; // Create divider sections. We should make at least ONE split. Cut(arePolygonsBuilt, xres, retrims); }
/// <summary> /// Updates info on the longest horizontal span that crosses this polygon (used /// by <see cref="GetLabelPosition"/>) /// </summary> /// <param name="y">The Y-value of the scan line.</param> /// <param name="minx">The X-value for the western end of the scan line.</param> /// <param name="maxx">The X-value for the eastern end of the scan line.</param> /// <param name="weight">Weighting factor to use when comparing span lengths versus /// the initial best length.</param> /// <param name="beststart">The position of the start of the best span.</param> /// <param name="bestend">The position of the end of the best span.</param> /// <param name="bestlen">The weighted length of the best span. This is what defines /// the meaning of "best".</param> void GetLabelSpan(double y, double minx, double maxx, double weight, ref IPosition beststart, ref IPosition bestend, ref double bestlen) { // Define scan line. ITerminal sloc = new FloatingTerminal(minx, y); ITerminal eloc = new FloatingTerminal(maxx, y); SegmentGeometry seg = new SegmentGeometry(sloc, eloc); // Intersect with the map IntersectionFinder xseg = new IntersectionFinder(seg, true); // Arrange intersections along the scan line. IntersectionResult xres = new IntersectionResult(xseg); xres.Sort(true); // Define start of the first span IPosition start = sloc; IPosition end = null; // Go through each successive intersection, to locate spans // that run through the interior of the polygon. foreach (IntersectionData d in xres.Intersections) { // If the intersection is a graze if (d.IsGraze) { // Just define the end of the graze as the end point (there's // no point in trying to locate a label along the graze). end = d.P2; } else { // Simple intersection... // Get the next intersection end = d.P1; // Get the midpoint of the span. IPosition mid = Position.CreateMidpoint(start, end); // If the midpoint really falls inside this polygon, see whether the span // length is bigger than what we already have (if anything). if (this.IsEnclosing(mid)) { double len = (end.X - start.X)/weight; if (len>bestlen) { bestlen = len; beststart = start; bestend = end; } } } start = end; } }