/// <summary> /// Compares two segments /// </summary> /// <param name="other"></param> /// <returns></returns> public int CompareTo(ISurfaceSegment other) { int retVal = 0; if (Start < other.Start) { retVal = -1; } else if (Start > other.Start) { retVal = 1; } else { // Same start, compare the ends if (End < other.End) { retVal = -1; } else if (End > other.End) { retVal = 1; } } return(retVal); }
/// <summary> /// Reduces the graph to the boundaries provided as parameter /// </summary> /// <param name="boundaries"></param> /// <returns>The reduced graph</returns> public void Reduce(List <ISegment> boundaries) { List <ISurfaceSegment> tmp = new List <ISurfaceSegment>(); int i = 0; while (i < Segments.Count) { ISurfaceSegment segment = Segments[i]; foreach (Segment newSegment in segment.Reduce(boundaries)) { tmp.Add(newSegment); } i += 1; } Segments = tmp; }
/// <summary> /// Performs an operation based on two surfaces. /// </summary> /// <param name="first">the first surface</param> /// <param name="second">the second surface</param> /// <param name="operation">the operation to perform on these graphs</param> /// <returns>the new graph</returns> private static Surface CombineTwoSurfaces(Surface first, Surface second, Segment.Op operation) { Surface retVal = new Surface(first.XParameter, first.YParameter); if (retVal.XParameter == null) { retVal.XParameter = second.XParameter; } if (retVal.YParameter == null) { retVal.YParameter = second.YParameter; } int i = 0; int j = 0; double start = 0; while (i < first.Segments.Count && j < second.Segments.Count) { ISurfaceSegment segment_i = first.Segments[i]; ISurfaceSegment segment_j = second.Segments[j]; if (segment_i.Start != segment_j.Start && start <= segment_i.Start && start <= segment_j.Start) { if (segment_i.Start < segment_j.Start) { // First consider segment_i where no segment_j is available if (segment_i.End <= segment_j.Start) { // No overlap IGraph val = operation(segment_i.Graph, null); retVal.AddSegment(new Segment(start, segment_i.End, val)); start = segment_i.End; i = i + 1; } else { // Overlap between segment_i and segment_j, segment_i is before segment_j IGraph val = operation(segment_i.Graph, null); retVal.AddSegment(new Segment(start, segment_j.Start, val)); start = segment_j.Start; } } else { // First consider segment_j where no segment_i is available if (segment_j.End <= segment_i.Start) { // No overlap IGraph val = operation(segment_j.Graph, null); retVal.AddSegment(new Segment(start, segment_j.End, val)); start = segment_j.End; j = j + 1; } else { // Overlap between segment_i and segment_j, segment_j is before segment_i IGraph val = operation(segment_j.Graph, null); retVal.AddSegment(new Segment(start, segment_i.Start, val)); start = segment_i.Start; } } } else { double end; if (segment_i.End < segment_j.End) { end = segment_i.End; i = i + 1; } else { if (segment_i.End == segment_j.End) { i = i + 1; } end = segment_j.End; j = j + 1; } IGraph val = operation(segment_i.Graph, segment_j.Graph); retVal.AddSegment(new Segment(start, end, val)); start = end; } } while (i < first.Segments.Count) { ISurfaceSegment segment_i = first.Segments[i]; IGraph val = operation(segment_i.Graph, null); retVal.AddSegment(new Segment(start, segment_i.End, val)); start = segment_i.End; i = i + 1; } while (j < second.Segments.Count) { ISurfaceSegment segment_j = second.Segments[j]; IGraph val = operation(null, segment_j.Graph); retVal.AddSegment(new Segment(start, segment_j.End, val)); start = segment_j.End; j = j + 1; } retVal.MergeDuplicates(); return(retVal); }
/// <summary> /// Merges a surface within this one, using the X axis as the merge orientation /// </summary> /// <param name="otherSurface"></param> public void MergeX(Surface otherSurface) { List <ISurfaceSegment> toProcess = new List <ISurfaceSegment>(otherSurface.Segments); List <ISurfaceSegment> toAdd = new List <ISurfaceSegment>(); while (toProcess.Count > 0) { ISurfaceSegment segment = toProcess[0]; toProcess.Remove(segment); // Reduce this segment according to the existing segments foreach (Segment existingSegment in Segments) { if (existingSegment.Start <= segment.Start) { if (existingSegment.End < segment.End) { if (existingSegment.End > segment.Start) { // The existing segment reduces the start of this segment segment.Start = existingSegment.End; } } else { // This segment is completely overriden by the existing segment; segment = null; break; } } else { // existingSegment.Start > segment.Start if (existingSegment.Start < segment.End) { if (existingSegment.End < segment.End) { // This segment splits the current segment in two. Segment newSegment = new Segment(existingSegment.End, segment.End, segment.Graph); toProcess.Insert(0, newSegment); } segment.End = existingSegment.Start; } else { // the existing segment does not impact this segment } } } if (segment != null) { if (segment.Start < segment.End) { toAdd.Add(segment); } } } Segments.AddRange(toAdd); Segments.Sort(); }
/// <summary> /// Constructor /// </summary> /// <param name="other">The other segment to copy</param> public Segment(ISurfaceSegment other) { Start = other.Start; End = other.End; Graph = other.Graph; }