public override void OnDone() { if (base.ActiveObject != null) { using (base.Frame.Project.Undo.UndoFrame) { if (iCurveOrg != null) // evtl. Einzelobjekt (Polyline oder Path) als Original rauslöschen { owner.Remove(iCurveOrg as IGeoObject); } ICurve[] iCurveList = new ICurve[blk.Count]; // der Pfad braucht eine Kurvenliste for (int i = 0; i < blk.Count; ++i) { iCurveList[i] = blk.Item(i) as ICurve; // von Block zu Liste } blk.Clear(); // weg mit dem Block, damit die Objekte nur einen owner haben base.ActiveObject = null; // damit der onDone-Mechanismus nichts einfügt if (Frame.GetBooleanSetting("Construct.MakePath", true)) { // das Ergebnis soll in einem Pfad zusammengefasst werden! Path path = Path.Construct(); path.Set(iCurveList); // macht den Path mit Header und so path.CopyAttributes(iCurveSel as IGeoObject); owner.Add(path); // nur zum owner des angeklickten Ursprungsobjekts } else { for (int i = 0; i < iCurveList.Length; ++i) { owner.Add(iCurveList[i] as IGeoObject); // nur zum owner des angeklickten Ursprungsobjekts } } if (iCurveOrg == null) // die Einzelelemente des CreateFromModel identifizieren //for (int i=0; i < iCurveList.Length; ++i) //{ // IGeoObject obj = (iCurveList[i] as IGeoObject).UserData.GetData("CADability.Path.Original") as IGeoObject; // if (obj!=null && obj.Owner!=null) obj.Owner.Remove(obj); // löschen //} { for (int i = 0; i < pathCreatedFromModel.Count; ++i) // über den ursprünglichen Pfad laufen { IGeoObject obj = null; if ((pathCreatedFromModel.Curve(i) as IGeoObject).UserData.ContainsData("CADability.Path.Original")) { obj = (pathCreatedFromModel.Curve(i) as IGeoObject).UserData.GetData("CADability.Path.Original") as IGeoObject; } if (obj != null && obj.Owner != null) { obj.Owner.Remove(obj); // löschen } (pathCreatedFromModel.Curve(i) as IGeoObject).UserData.RemoveUserData("CADability.Path.Original"); } } } base.ActiveObject = null; } base.OnDone(); }
public override void OnDone() { if (validResult && ActiveObject != null) { Solid sld = shell.Owner as Solid; if (sld != null) { // the shell was part of a Solid IGeoObjectOwner owner = sld.Owner; // Model or Block using (Frame.Project.Undo.UndoFrame) { owner.Remove(sld); Solid replacement = Solid.MakeSolid(ActiveObject as Shell); replacement.CopyAttributes(sld); owner.Add(replacement); if (!string.IsNullOrEmpty(parametricsName) && parametricProperty != null) { parametricProperty.Name = parametricsName; replacement.Shells[0].AddParametricProperty(parametricProperty); } } } else { IGeoObjectOwner owner = shell.Owner; using (Frame.Project.Undo.UndoFrame) { owner.Remove(shell); owner.Add(ActiveObject); } } } ActiveObject = null; base.OnDone(); }
public override void OnDone() { if (validResult && ActiveObject != null) { using (Frame.Project.Undo.UndoFrame) { Solid sld = shell.Owner as Solid; if (sld != null) { // the shell was part of a Solid IGeoObjectOwner owner = sld.Owner; // Model or Block owner.Remove(sld); Solid replacement = Solid.MakeSolid(ActiveObject as Shell); owner.Add(replacement); } else { IGeoObjectOwner owner = shell.Owner; owner.Remove(shell); owner.Add(ActiveObject); } } } ActiveObject = null; base.OnDone(); }
public override void OnDone() { if (edges.Count > 0) { IGeoObject[] affected; IGeoObject[] modified = Make3D.MakeChamfer(theFace, edges.ToArray(), dist1, dist2, out affected); if (affected.Length > 0) { using (Frame.Project.Undo.UndoFrame) { IGeoObjectOwner owner = null; for (int i = 0; i < affected.Length; ++i) { if (owner == null || affected[i].Owner is Model) { owner = affected[i].Owner; } affected[i].Owner.Remove(affected[i]); } for (int i = 0; i < modified.Length; ++i) { owner.Add(modified[i]); } } } } base.OnDone(); }
bool ICommandHandler.OnCommand(string MenuId) { switch (MenuId) { case "MenuId.Fillet.ChangeRadius": ParametricsRadius pr = new ParametricsRadius(involvedFaces, selectActionContextMenu.soa.Frame, true); selectActionContextMenu.soa.Frame.SetAction(pr); return(true); case "MenuId.Fillet.Remove": Shell orgShell = involvedFaces[0].Owner as Shell; if (orgShell != null) { RemoveFillet rf = new RemoveFillet(involvedFaces[0].Owner as Shell, new HashSet <Face>(involvedFaces)); Shell sh = rf.Result(); if (sh != null) { using (selectActionContextMenu.soa.Frame.Project.Undo.UndoFrame) { sh.CopyAttributes(orgShell); IGeoObjectOwner owner = orgShell.Owner; owner.Remove(orgShell); owner.Add(sh); } } } return(true); } return(false); }
virtual public bool OnCommand(string MenuId) { switch (MenuId) { case "MenuId.Explode": if (Frame.ActiveAction is SelectObjectsAction) { using (Frame.Project.Undo.UndoFrame) { IGeoObjectOwner addTo = dimension.Owner; if (addTo == null) { addTo = Frame.ActiveView.Model; } GeoObjectList toSelect = dimension.Decompose(); addTo.Remove(dimension); for (int i = 0; i < toSelect.Count; ++i) { addTo.Add(toSelect[i]); } SelectObjectsAction soa = Frame.ActiveAction as SelectObjectsAction; soa.SetSelectedObjects(toSelect); // alle Teilobjekte markieren } } return(true); } return(false); }
/// <summary> /// Implements <see cref="CADability.UserInterface.ICommandHandler.OnCommand (string)"/> /// </summary> /// <param name="MenuId"></param> /// <returns></returns> virtual public bool OnCommand(string MenuId) { switch (MenuId) { case "MenuId.Explode": if (frame.ActiveAction is SelectObjectsAction) { using (frame.Project.Undo.UndoFrame) { IGeoObjectOwner addTo = blockRef.Owner; if (addTo == null) { addTo = frame.ActiveView.Model; } addTo.Remove(blockRef); //IGeoObject go = blockRef.ReferencedBlock.Clone(); //go.PropagateAttributes(blockRef.Layer, blockRef.ColorDef); GeoObjectList l = blockRef.Decompose(); addTo.Add(l[0]); SelectObjectsAction soa = frame.ActiveAction as SelectObjectsAction; soa.SetSelectedObjects(l); // alle Teilobjekte markieren } } return(true); } return(false); }
virtual public bool OnCommand(string MenuId) { switch (MenuId) { case "MenuId.Reverse": polyline.Reverse(); return(true); case "MenuId.CurveSplit": Frame.SetAction(new ConstrSplitCurve(polyline)); return(true); case "MenuId.Explode": if (Frame.ActiveAction is SelectObjectsAction) { using (Frame.Project.Undo.UndoFrame) { IGeoObjectOwner addTo = polyline.Owner; if (addTo == null) { addTo = Frame.ActiveView.Model; } GeoObjectList toSelect = polyline.Decompose(); addTo.Remove(polyline); for (int i = 0; i < toSelect.Count; ++i) { addTo.Add(toSelect[i]); } SelectObjectsAction soa = Frame.ActiveAction as SelectObjectsAction; soa.SetSelectedObjects(toSelect); // alle Teilobjekte markieren } } return(true); case "MenuId.Aequidist": Frame.SetAction(new ConstructAequidist(polyline)); return(true); case "MenuId.Path.Vertex.StartWithMe": { if (polyline.IsClosed) { GeoPointProperty gpp = Frame.ContextMenuSource as GeoPointProperty; if (gpp != null) { if (gpp.UserData.ContainsData("Index")) { int index = (int)gpp.UserData.GetData("Index"); polyline.CyclicalPermutation(index); } } } } return(true); } return(false); }
virtual public bool OnCommand(string MenuId) { switch (MenuId) { case "MenuId.Explode": if (Frame.ActiveAction is SelectObjectsAction) { SelectObjectsAction soa = Frame.ActiveAction as SelectObjectsAction; soa.SetSelectedObjects(new GeoObjectList()); //Application.DoEvents(); using (Frame.Project.Undo.UndoFrame) { IGeoObjectOwner addTo = block.Owner; if (addTo == null) { addTo = Frame.ActiveView.Model; } addTo.Remove(block); GeoObjectList toSelect = block.Decompose(); for (int i = 0; i < toSelect.Count; i++) { addTo.Add(toSelect[i]); } soa.SetSelectedObjects(toSelect); // alle Teilobjekte markieren } } return(true); case "MenuId.SelectedObject.ToBackground": if (ContextMenuSource != null) { block.MoveToBack(ContextMenuSource); subEntries = null; if (propertyPage != null) { propertyPage.Refresh(this); } } return(true); case "MenuId.SelectedObject.ToForeground": if (ContextMenuSource != null) { block.MoveToFront(ContextMenuSource); subEntries = null; if (propertyPage != null) { propertyPage.Refresh(this); } } return(true); } return(false); }
public override void OnDone() { base.ActiveObject = null; if (trimCurve != null) // nur dann gibts was zu tun! { using (base.Frame.Project.Undo.UndoFrame) { if (deleteObject) { owner.Remove(iCurve as IGeoObject); // original Löschen } else { if (iCurve.IsClosed) // geschlosene Kurve, also z.B. Kreis { iCurve.Trim(param2, param1); // an zwei Parametern geschnitten } else { // if (!Precision.IsEqual(trimCurve.StartPoint, iCurve.StartPoint) && !Precision.IsEqual(trimCurve.EndPoint, iCurve.EndPoint)) if ((param1 > 1e-8) && (param2 < (1.0 - 1e-8))) { // mittendrinn´da parameter beide innerhalb der Kurve! ICurve trimCurveTemp; trimCurveTemp = iCurve.Clone(); iCurve.Trim(0.0, param1); // Kurve auf das untere Stück verkürzt (trimCurveTemp as IGeoObject).CopyAttributes(iCurve as IGeoObject); trimCurveTemp.Trim(param2, 1.0); // Kopie als oberes Stück owner.Add(trimCurveTemp as IGeoObject); } else { if (Precision.IsEqual(trimCurve.StartPoint, iCurve.StartPoint)) // der Anfang muss weg { iCurve.Trim(param1, 1.0); } if (Precision.IsEqual(trimCurve.EndPoint, iCurve.EndPoint)) // das Ende muss weg { iCurve.Trim(0.0, param2); } } } } } } sourceCurveSave = sourceCurve; base.OnDone(); }
public override void OnDone() { if (base.ActiveObject != null) { base.ActiveObject = null; using (base.Frame.Project.Undo.UndoFrame) { owner.Remove(iCurve as IGeoObject); // original Löschen for (int i = 0; i < trimCurves.Length; ++i) // alle einfügen { (trimCurves[i] as IGeoObject).CopyAttributes(iCurve as IGeoObject); owner.Add(trimCurves[i] as IGeoObject); } } } base.OnDone(); }
internal static void Approximate(IFrame frame, IGeoObject toApproximate) { // die Approximation gemäß globaler Einstellung aus einem ShowProperty heraus, // also mit SelectObjectsAction als aktiver Aktion ICurve app = (toApproximate as ICurve).Approximate(frame.GetIntSetting("Approximate.Mode", 0) == 0, frame.GetDoubleSetting("Approximate.Precision", 0.01)); Actions.SelectObjectsAction soa = frame.ActiveAction as Actions.SelectObjectsAction; IGeoObjectOwner addTo = toApproximate.Owner; if (addTo == null) { addTo = frame.ActiveView.Model; } using (frame.Project.Undo.UndoFrame) { addTo.Remove(toApproximate); IGeoObject go = app as IGeoObject; go.CopyAttributes(toApproximate); addTo.Add(go); soa.SetSelectedObjects(new GeoObjectList(go)); } }
public override void OnDone() { // zerstückeln, original entfernen und Stücke einfügen // TODO: noch auf 0.0 aufpassen! // TODO: Polyline geht nicht richtig, Ellipse auch nicht, da nicht linear auf dem Umfang IGeoObject go = theCurve as IGeoObject; if (go != null) { IGeoObjectOwner owner = go.Owner; if (owner != null) { using (Frame.Project.Undo.UndoFrame) { //if (go is Polyline) //{ // (go as Polyline).IsClosed = false; // aufbrechen //} // nicht aufbrechen, das ist jetzt in Split ordentlich geregelt owner.Remove(go); ICurve toSplit = theCurve; double totlen = theCurve.Length; double sumlen = 0.0; for (int i = 0; i < number; ++i) { ICurve splitted = toSplit.Clone(); double start = theCurve.PositionAtLength(sumlen); sumlen += sections[i] * totlen; double end = theCurve.PositionAtLength(sumlen); splitted.Trim(start, end); (splitted as IGeoObject).CopyAttributes(go); owner.Add(splitted as IGeoObject); } //double[] Positions = new double[number]; //for (int i = 0; i < number; ++i) //{ // double sum = 0.0; // for (int j = i; j < number; ++j) // { // sum += sections[j]; // } // Positions[i] = sections[i] / sum; //} //for (int i = 0; i < number-1; ++i) //{ // ICurve[] splitted = toSplit.Split(Positions[i]); // if (splitted.Length == 2) // { // IGeoObject toAdd = splitted[0] as IGeoObject; // toAdd.CopyAttributes(go); // owner.Add(toAdd); // toSplit = splitted[1]; // } //} //(toSplit as IGeoObject).CopyAttributes(go); //owner.Add(toSplit as IGeoObject); } } } base.OnDone(); }
virtual public bool OnCommand(string MenuId) { switch (MenuId) { case "MenuId.Reverse": (path as ICurve).Reverse(); if (propertyPage != null) { propertyPage.Refresh(this); } return(true); case "MenuId.CurveSplit": Frame.SetAction(new ConstrSplitCurve(path)); return(true); case "MenuId.Approximate": if (Frame.ActiveAction is SelectObjectsAction) { Curves.Approximate(Frame, path); } return(true); case "MenuId.Explode": if (Frame.ActiveAction is SelectObjectsAction) { using (Frame.Project.Undo.UndoFrame) { IGeoObjectOwner addTo = path.Owner; if (addTo == null) { addTo = Frame.ActiveView.Model; } ICurve[] pathCurves = path.Curves; GeoObjectList toSelect = path.Decompose(); addTo.Remove(path); for (int i = toSelect.Count - 1; i >= 0; --i) { if (!toSelect[i].HasValidData()) { toSelect.Remove(i); } } for (int i = 0; i < toSelect.Count; i++) { addTo.Add(toSelect[i]); } SelectObjectsAction soa = Frame.ActiveAction as SelectObjectsAction; soa.SetSelectedObjects(toSelect); // alle Teilobjekte markieren } } return(true); case "MenuId.Aequidist": Frame.SetAction(new ConstructAequidist(path)); return(true); case "MenuId.Reduce": if (path.GetPlanarState() == PlanarState.Planar) { Plane pln = path.GetPlane(); Path2D p2d = path.GetProjectedCurve(pln) as Path2D; if (p2d != null) { p2d.ForceConnected(); Reduce2D r2d = new Reduce2D(); r2d.Precision = Settings.GlobalSettings.GetDoubleValue("Approximate.Precision", 0.01); r2d.Add(p2d.SubCurves); r2d.OutputMode = Reduce2D.Mode.Paths; ICurve2D[] red = r2d.Reduced; if (red.Length == 1) { using (Frame.Project.Undo.UndoFrame) { IGeoObjectOwner addTo = path.Owner; if (addTo == null) { addTo = Frame.ActiveView.Model; } addTo.Remove(path); Path redpath = red[0].MakeGeoObject(pln) as Path; if (redpath != null) { SelectObjectsAction soa = Frame.ActiveAction as SelectObjectsAction; soa.SetSelectedObjects(new GeoObjectList(redpath)); } } } } } return(true); } return(false); }
/// <summary> /// Overrides <see cref="CADability.Actions.ConstructAction.OnDone ()"/> /// </summary> public override void OnDone() { if (base.ActiveObject != null) { using (base.Frame.Project.Undo.UndoFrame) { Boolean doIt = true; // alten Pfad entfernen if (composedSplit) { if (iCurveComposedSplit != null) { (iCurveComposedSplit as IGeoObject).Owner.Remove(iCurveComposedSplit as IGeoObject); } else { // die Einzelelemente des CreateFromModel identifizieren for (int j = 0; j < pathCreatedFromModel.Count; ++j) { IGeoObject obj = null; if ((pathCreatedFromModel.Curve(j) as IGeoObject).UserData.ContainsData("CADability.Path.Original")) { obj = (pathCreatedFromModel.Curve(j) as IGeoObject).UserData.GetData("CADability.Path.Original") as IGeoObject; } if (obj != null && obj.Owner != null) { obj.Owner.Remove(obj); // löschen } } } } //if (composedSingle) //{ // if (iCurve1.PositionOf(arc.StartPoint) < iCurve1.PositionOf(arc.EndPoint)) // iCurve1.Trim(iCurve1.PositionOf(arc.StartPoint), iCurve1.PositionOf(arc.EndPoint)); // else iCurve1.Trim(iCurve1.PositionOf(arc.EndPoint), iCurve1.PositionOf(arc.StartPoint)); //} //else { if (roundRad == 0.0) { if (iCurve1.PositionOf(objectPointSav) > 0.5) { iCurve1.Trim(0.0, iCurve1.PositionOf(objectPointSav)); } else { iCurve1.Trim(iCurve1.PositionOf(objectPointSav), 1.0); if (Frame.GetBooleanSetting("Construct.MakePath", true)) { iCurve1.Reverse(); } } if (iCurve2.PositionOf(objectPointSav) > 0.5) { iCurve2.Trim(0.0, iCurve2.PositionOf(objectPointSav)); if (Frame.GetBooleanSetting("Construct.MakePath", true)) { iCurve2.Reverse(); } } else { iCurve2.Trim(iCurve2.PositionOf(objectPointSav), 1.0); } } else { if (iCurve1.PositionOf(arc.StartPoint) > iCurve1.PositionOf(arc.Center)) { iCurve1.Reverse(); } // evtl. umdrehen, damit das Trimmen unten klappt if (iCurve2.PositionOf(arc.EndPoint) < iCurve2.PositionOf(arc.Center)) { iCurve2.Reverse(); } // evtl. umdrehen, damit das Trimmen unten klappt if (iCurve1.IsClosed) { // um nur die letzte Linie/Element wegzutrimmen und nicht größere Teile if (iCurve1 is Path) { // setzt den Anfangspunkt so um, dass das Segment am arc.StartPoint das letzte ist (iCurve1 as Path).CyclicalPermutation(arc.StartPoint, false); } if (iCurve1 is Polyline) { // setzt den Anfangspunkt so um, dass das Segment am arc.StartPoint das erste ist (iCurve1 as Polyline).CyclicalPermutation(arc.StartPoint, false); } } if (iCurve2.IsClosed) { // um nur die letzte Linie/Element wegzutrimmen und nicht größere Teile if (iCurve2 is Path) { // setzt den Anfangspunkt so um, dass das Segment am arc.StartPoint das letzte ist (iCurve2 as Path).CyclicalPermutation(arc.EndPoint, true); } if (iCurve2 is Polyline) { // setzt den Anfangspunkt so um, dass das Segment am arc.StartPoint das erste ist (iCurve2 as Polyline).CyclicalPermutation(arc.EndPoint, true); } } double trimBorderCurve1End = iCurve1.PositionOf(arc.StartPoint); double trimBorderCurve2Start = iCurve2.PositionOf(arc.EndPoint); if ((trimBorderCurve1End > 0.0) && (trimBorderCurve2Start < 1.0)) { iCurve1.Trim(0.0, trimBorderCurve1End); iCurve2.Trim(trimBorderCurve2Start, 1.0); } else { doIt = false; } //iCurve1.Trim(0.0,iCurve1.PositionOf(arc.StartPoint)); //iCurve2.Trim(iCurve2.PositionOf(arc.EndPoint),1.0); //if (iCurve1.PositionOf(objectPointSav) > 0.5) // iCurve1.Trim(0.0,iCurve1.PositionOf(arc.StartPoint)); //else //{ // iCurve1.Trim(iCurve1.PositionOf(arc.StartPoint),1.0); // if (Frame.GetBooleanSetting("Construct.MakePath",true)) iCurve1.Reverse(); //} //if (iCurve2.PositionOf(objectPointSav) > 0.5) //{ // iCurve2.Trim(0.0,iCurve2.PositionOf(arc.EndPoint)); // if (Frame.GetBooleanSetting("Construct.MakePath",true)) iCurve2.Reverse(); //} //else iCurve2.Trim(iCurve2.PositionOf(arc.EndPoint),1.0); } } if (doIt) { (arc as IGeoObject).CopyAttributes(iCurve1 as IGeoObject); if (Frame.GetBooleanSetting("Construct.MakePath", true) || composedSingle2Objects) { // das Ergebnis soll in einem Pfad zusammengefasst werden! Path tmpPath = Path.Construct(); tmpPath.Add(iCurve1); if (roundRad > 0.0) { tmpPath.Add(arc); } // if (!composedSingle) tmpPath.Add(iCurve2); if (composedSingle2Objects) { tmpPath.Add(iCurveComposedSingle2Objects); } (tmpPath as IGeoObject).CopyAttributes(iCurve1 as IGeoObject); tmpPath.Flatten(); // bringt alles auf die "geometrische" Ebene, Unterpfade werden aufgelöst owner.Add(tmpPath as IGeoObject); } else { if (roundRad > 0.0) { owner.Add(arc as IGeoObject); } if (composedSplit) { // da neu erzeugt von SplitAtMousePosition, hier explizit einfügen owner.Add(iCurve1 as IGeoObject); owner.Add(iCurve2 as IGeoObject); } //if (composedSingle) //{ // // da neu erzeugt, hier explizit einfügen // owner.Add(iCurve1 as IGeoObject); //} } } } base.ActiveObject = null; } base.OnDone(); }
private List <MenuWithHandler> GetFacesSubmenus(Face face) { List <MenuWithHandler> res = new List <MenuWithHandler>(); if (face.IsFillet()) { HashSet <Face> connectedFillets = new HashSet <Face>(); CollectConnectedFillets(face, connectedFillets); FeatureCommandHandler fch = new FeatureCommandHandler(connectedFillets.ToArray(), this, "MenuId.Fillet"); MenuWithHandler fr = new MenuWithHandler("MenuId.Fillet.ChangeRadius"); fr.OnCommand = (menuId) => { ParametricsRadius pr = new ParametricsRadius(connectedFillets.ToArray(), soa.Frame, true); soa.Frame.SetAction(pr); return(true); }; fr.OnSelected = (mh, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(connectedFillets.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; MenuWithHandler fd = new MenuWithHandler("MenuId.Fillet.Remove"); fd.OnCommand = (menuId) => { Face[] involvedFaces = connectedFillets.ToArray(); Shell orgShell = involvedFaces[0].Owner as Shell; if (orgShell != null) { RemoveFillet rf = new RemoveFillet(involvedFaces[0].Owner as Shell, new HashSet <Face>(involvedFaces)); Shell sh = rf.Result(); if (sh != null) { using (soa.Frame.Project.Undo.UndoFrame) { sh.CopyAttributes(orgShell); IGeoObjectOwner owner = orgShell.Owner; owner.Remove(orgShell); owner.Add(sh); } } } soa.ResetMode(); return(true); }; fd.OnSelected = (mh, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(connectedFillets.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; fch.SubMenus = new MenuWithHandler[] { fr, fd }; res.Add(fch); } IEnumerable <Face> connected = face.GetSameSurfaceConnected(); // if (connected.Any()) { List <Face> lconnected = new List <Face>(connected); lconnected.Add(face); BoundingCube ext = BoundingCube.EmptyBoundingCube; foreach (Face fc in connected) { ext.MinMax(fc.GetExtent(0.0)); } // maybe a full sphere, cone, cylinder or torus: // except for the sphere: position axis // except for the cone: change radius or diameter // for the cone: smaller and larger diameter // for cone and cylinder: total length if (face.Surface is CylindricalSurface || face.Surface is CylindricalSurfaceNP || face.Surface is ToroidalSurface) { MenuWithHandler mh = new MenuWithHandler("MenuId.FeatureDiameter"); mh.OnCommand = (menuId) => { ParametricsRadius pr = new ParametricsRadius(lconnected.ToArray(), soa.Frame, false); soa.Frame.SetAction(pr); return(true); }; mh.OnSelected = (menuId, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(lconnected.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; res.Add(mh); } if (face.Surface is CylindricalSurface || face.Surface is CylindricalSurfaceNP || face.Surface is ConicalSurface) { Line axis = null; if (face.Surface is ICylinder cyl) { axis = cyl.Axis.Clip(ext); } if (face.Surface is ConicalSurface cone) { axis = cone.AxisLine(face.Domain.Bottom, face.Domain.Top); } MenuWithHandler mh = new MenuWithHandler("MenuId.AxisPosition"); mh.OnCommand = (menuId) => { ParametricsDistanceActionOld pd = new ParametricsDistanceActionOld(lconnected, axis, soa.Frame); soa.Frame.SetAction(pd); return(true); }; mh.OnSelected = (menuId, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(lconnected.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; res.Add(mh); } } if (face.Surface is PlaneSurface pls) { // try to find parallel outline edges to modify the distance Edge[] outline = face.OutlineEdges; for (int j = 0; j < outline.Length - 1; j++) { for (int k = j + 1; k < outline.Length; k++) { if (outline[j].Curve3D is Line l1 && outline[k].Curve3D is Line l2) { if (Precision.SameDirection(l1.StartDirection, l2.StartDirection, false)) { // two parallel outline lines, we could parametrize the distance Edge o1 = outline[j]; Edge o2 = outline[k]; // outline[i] is not captured correctly for the anonymous method. I don't know why. With local copies, it works. double lmin = double.MaxValue; double lmax = double.MinValue; double p = Geometry.LinePar(l1.StartPoint, l1.EndPoint, l2.StartPoint); lmin = Math.Min(lmin, p); lmax = Math.Max(lmax, p); p = Geometry.LinePar(l1.StartPoint, l1.EndPoint, l2.EndPoint); lmin = Math.Max(Math.Min(lmin, p), 0); lmax = Math.Min(Math.Max(lmax, p), 1); GeoPoint p1 = Geometry.LinePos(l1.StartPoint, l1.EndPoint, (lmin + lmax) / 2.0); GeoPoint p2 = Geometry.DropPL(p1, l2.StartPoint, l2.EndPoint); if ((p1 | p2) > Precision.eps) { MenuWithHandler mh = new MenuWithHandler("MenuId.EdgeDistance"); Line feedback = Line.TwoPoints(p1, p2); GeoObjectList feedbackArrow = currentView.Projection.MakeArrow(p1, p2, pls.Plane, Projection.ArrowMode.circleArrow); mh.OnCommand = (menuId) => { ParametricsDistanceActionOld pd = new ParametricsDistanceActionOld(o1, o2, feedback, pls.Plane, soa.Frame); soa.Frame.SetAction(pd); return(true); }; mh.OnSelected = (m, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(feedbackArrow); currentMenuSelection.Add(o1.OtherFace(face)); currentMenuSelection.Add(o2.OtherFace(face)); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; res.Add(mh); } } } } } } if (res.Count > 6) { List <MenuWithHandler> lm = new List <MenuWithHandler>(); for (int i = 4; i < res.Count; i++) { lm.Add(res[i]); } res.RemoveRange(4, lm.Count); MenuWithHandler subMenu = new MenuWithHandler("MenuId.More"); subMenu.SubMenus = lm.ToArray(); res.Add(subMenu); } return(res); }