/// <summary> /// The menu items for this tree node /// </summary> /// <returns></returns> protected override List <MenuItem> GetMenuItems() { List <MenuItem> retVal = base.GetMenuItems(); retVal.Add(new MenuItem("-")); retVal.Add(new MenuItem("Add parameter", new EventHandler(AddParameterHandler))); retVal.Add(new MenuItem("Add case", new EventHandler(AddCaseHandler))); retVal.Add(new MenuItem("-")); DataDictionary.Interpreter.InterpretationContext context = new DataDictionary.Interpreter.InterpretationContext(Item); if (Item.FormalParameters.Count == 1) { Parameter parameter = (Parameter)Item.FormalParameters[0]; DataDictionary.Functions.Graph graph = Item.createGraph(context, parameter); if (graph != null && graph.Segments.Count != 0) { retVal.Add(new MenuItem("Display", new EventHandler(DisplayHandler))); retVal.Add(new MenuItem("-")); } } else if (Item.FormalParameters.Count == 2) { DataDictionary.Functions.Surface surface = Item.createSurface(context); if (surface != null && surface.Segments.Count != 0) { retVal.Add(new MenuItem("Display", new EventHandler(DisplayHandler))); retVal.Add(new MenuItem("-")); } } retVal.Add(new MenuItem("Delete", new EventHandler(DeleteHandler))); return(retVal); }
/// <summary> /// Combines two surfaces by replacing in this the value of second /// on each segment of this == def /// </summary> /// <param name="second"></param> /// <param name="def"></param> /// <returns></returns> public Surface Override(Surface second) { return(CombineTwoSurfaces(this, second, Segment.Override)); }
/// <summary> /// Selects the minimum surface /// </summary> /// <param name="second"></param> /// <param name="def"></param> /// <returns></returns> public Surface Min(Surface second) { return(CombineTwoSurfaces(this, second, Segment.Min)); }
/// <summary> /// Multiplies two surfaces /// </summary> /// <param name="other"></param> /// <returns></returns> public Surface MultiplySurface(Surface other) { return(CombineTwoSurfaces(this, other, Segment.Mult)); }
/// <summary> /// Divides two surfaces /// </summary> /// <param name="other"></param> /// <returns></returns> public Surface DivideSurface(Surface other) { return(CombineTwoSurfaces(this, other, Segment.Divide)); }
/// <summary> /// Substract two surfaces /// </summary> /// <param name="other"></param> /// <returns></returns> public Surface SubstractSurface(Surface other) { return(CombineTwoSurfaces(this, other, Segment.Substract)); }
/// <summary> /// Adds two surfaces /// </summary> /// <param name="other"></param> /// <returns></returns> public Surface AddSurface(Surface other) { return(CombineTwoSurfaces(this, other, Segment.Add)); }
/// <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 /// <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) { Segment segment_i = first.Segments[i]; Segment 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 Graph 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 Graph 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 Graph 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 Graph 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; } Graph val = operation(segment_i.Graph, segment_j.Graph); retVal.AddSegment(new Segment(start, end, val)); start = end; } } while (i < first.Segments.Count) { Segment segment_i = first.Segments[i]; Graph 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) { Segment segment_j = second.Segments[j]; Graph 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 tow surfaces, using the Y axis as the merge orientation /// </summary> /// <param name="otherSurface"></param> public static Surface MergeY(Surface first, Surface second) { return(CombineTwoSurfaces(first, second, Segment.Merge)); }
/// <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 <Segment> toProcess = new List <Segment>(otherSurface.Segments); List <Segment> toAdd = new List <Segment>(); while (toProcess.Count > 0) { Segment 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(); }