public override void OnDone() { if (base.ActiveObject != null) { using (base.Frame.Project.Undo.UndoFrame) { CurrentMouseView.Canvas.Cursor = "WaitCursor"; GeoObjectList ToAdd = new GeoObjectList(); Model m = base.Frame.ActiveView.Model; BRepOperation brepOp = new BRepOperation(toSplit.Shells[0], plane); (Shell[] upper, Shell[] lower) = BRepOperation.SplitByPlane(toSplit.Shells[0], plane); for (int i = 0; i < upper.Length; i++) { ToAdd.Add(Solid.MakeSolid(upper[i])); } for (int i = 0; i < lower.Length; i++) { ToAdd.Add(Solid.MakeSolid(lower[i])); } m.Remove(toSplit); m.Add(ToAdd); base.ActiveObject = null; base.OnDone(); } } }
bool curveInputPath(ConstructAction.CurveInput sender, ICurve[] Curves, bool up) { // ... nur die sinnvollen Kurven verwenden objectPoint = base.CurrentMousePosition; if (up) { if (Curves.Length == 0) { sender.SetCurves(Curves, null); // ...die werden jetzt im ControlCenter dargestellt (nur bei up) } else { sender.SetCurves(Curves, Curves[0]); } } if (Curves.Length > 0) { // er hat was gewählt selectedObjectsList.Clear(); base.FeedBack.ClearSelected(); selectedObjectsList.Add(Curves[0] as IGeoObject); // das eine in die Liste ListDefault(1); // die Listen löschen und mit "1" vorbesetzen if (extrudeOrg()) { return(true); } } heightInput.ReadOnly = false; base.FeedBack.ClearSelected(); base.ShowActiveObject = false; return(false); }
bool geoObjectInputFace(ConstructAction.GeoObjectInput sender, IGeoObject[] TheGeoObjects, bool up) { // ... nur die sinnvollen Kurven verwenden // TODO: evtl Mehrfachanwahl ermöglichen if (up) { if (TheGeoObjects.Length == 0) { sender.SetGeoObject(TheGeoObjects, null); // ...die werden jetzt im ControlCenter dargestellt (nur bei up) } else { sender.SetGeoObject(TheGeoObjects, TheGeoObjects[0]); } } if (TheGeoObjects.Length > 0) { // er hat was gewählt selectedObjectsList.Clear(); base.FeedBack.ClearSelected(); selectedObjectsList.Add(TheGeoObjects[0]); // das eine in die Liste ListDefault(1); // die Listen löschen und mit "1" vorbesetzen if (makeFaceOrg()) { return(true); } } base.ShowActiveObject = false; base.FeedBack.ClearSelected(); return(false); }
public override void OnDone() { if (base.ActiveObject != null) { using (base.Frame.Project.Undo.UndoFrame) { Frame.ActiveView.Canvas.Cursor = "WaitCursor"; GeoObjectList ToAdd = new GeoObjectList(); Model m = base.Frame.ActiveView.Model; PlaneSurface pls = new PlaneSurface(plane); for (int i = 0; i < m.Count; ++i) // durch das ganze Modell laufen { ICurve[] crvs = Intersect(m[i], pls); if (crvs != null) { for (int k = 0; k < crvs.Length; k++) { IGeoObject go = crvs[k] as IGeoObject; go.CopyAttributes(base.ActiveObject); ToAdd.Add(go); } } } m.Add(ToAdd); base.KeepAsLastStyle(ActiveObject); base.ActiveObject = null; base.OnDone(); } } }
public override void OnDone() { // ist die Shift Taste gehalten, so werden Kopien gemacht, d.h. der die Elemente // des blocks werden eingefügt. Ansonsten werden die original-Objekte verändert // TODO: Feedback über Cursor bei Shift-Taste fehlt noch // TODO: die neuen oder veränderten Objekte sollten markiert sein. using (Frame.Project.Undo.UndoFrame) { ModOp m = ModOp.Translate(offset); if (((Frame.UIService.ModifierKeys & Keys.Shift) != 0) || copyObject) { GeoObjectList cloned = new GeoObjectList(); foreach (IGeoObject go in originals) { IGeoObject cl = go.Clone(); cl.Modify(m); // go.Owner.Add(cl); cloned.Add(cl); } base.Frame.Project.GetActiveModel().Add(cloned); } else { originals.Modify(m); } } base.ActiveObject = null; // damit es nicht gleich eingefügt wird base.OnDone(); }
/// <summary> /// This method is used by a <see cref="Hatch"/> object to calculate its contents. It generates a /// set of parallel lines according to <see cref="LineDistance"/> and <see cref="LineAngle"/> /// and clips them with the given shape. The lines are projected into the 3D world /// by the given plane. <seealso cref="CompoundShape.Clip"/> /// </summary> /// <param name="shape">shape of the hatch object</param> /// <param name="plane">local plane of the hatch object</param> /// <returns></returns> public override GeoObjectList GenerateContent(CompoundShape shape, Plane plane) { GeoObjectList res = new GeoObjectList(); if (shape == null) { return(res); } if (marginOffset != 0.0) { shape.Approximate(false, Settings.GlobalSettings.GetDoubleValue("Approximate.Precision", 0.01)); shape = shape.Shrink(marginOffset); } for (int i = 0; i < Math.Max(1, number); ++i) { double a = lineAngle.Radian + i * (double)offset; ModOp2D m = ModOp2D.Rotate(new SweepAngle(-a)); BoundingRect ext = shape.GetExtent(); ext.Modify(m); // ext ist jetzt waagrecht, u.U. zu groß, was aber egal ist m = ModOp2D.Rotate(new SweepAngle(a)); // die umgekehrte ModOp int alt = 0; // eine Linie soll durch die Mitte gehen double c = (ext.Bottom + ext.Top) / 2.0; double num = Math.Ceiling((c - ext.Bottom) / lineDistance); ext.Bottom = c - num * lineDistance; // das untere Ende sowei nach unten verschoben, dass eine Linie durch die mitte geht // das ist wichtig, weil sonst manche Schraffuren nicht zu picken sind, da keine Linie darin erscheint // da eine Schraffur meist nur aus einem SimpleShape besteht, gibt es immer eine Linie durch die Mitte for (double y = ext.Bottom; y < ext.Top; y += lineDistance) { GeoPoint2D startPoint = m * new GeoPoint2D(ext.Left, y); GeoPoint2D endPoint = m * new GeoPoint2D(ext.Right, y); Line2D l = new Line2D(startPoint, endPoint); if (alternate && ((alt & 0x01) != 0)) { l.Reverse(); } double[] seg = shape.Clip(l, true); for (int j = 0; j < seg.Length; j += 2) { IGeoObject go = l.Trim(seg[j], seg[j + 1]).MakeGeoObject(plane); (go as ILineWidth).LineWidth = lineWidth; (go as ILinePattern).LinePattern = linePattern; (go as IColorDef).ColorDef = colorDef; res.Add(go); } ++alt; } } return(res); }
public override GeoObjectList GenerateContent(CompoundShape shape, Plane plane) { GeoObjectList res = new GeoObjectList(); for (int i = 0; i < shape.SimpleShapes.Length; ++i) { SimpleShape ss = shape.SimpleShapes[i].Clone(); ss.Flatten(); // es entstehen Shapes mit Polylinien, das ist für Faces schlecht Face fc = Face.MakeFace(new PlaneSurface(plane), ss); fc.ColorDef = color; res.Add(fc); } return(res); }
public Constr3DScrewPath(GeoObjectList selectedObjects) { GeoObjectList clones = selectedObjects.CloneObjects(); if (selectedObjects.Count == 1) { if (selectedObjects[0] is Hatch) { shape = (selectedObjects[0] as Hatch).CompoundShape; plane = (selectedObjects[0] as Hatch).Plane; return; } else if (selectedObjects[0] is Face) { if ((selectedObjects[0] as Face).Surface is PlaneSurface) { // here we could directely set shape and plane } clones.Clear(); foreach (Edge edg in (selectedObjects[0] as Face).AllEdgesIterated()) { if (edg.Curve3D != null) { clones.Add(edg.Curve3D as IGeoObject); } } } } shape = CompoundShape.CreateFromList(clones, Precision.eps, out plane); if (shape == null) { Path toRotate = Path.Construct(); toRotate.Set(clones, false, Precision.eps); if (toRotate.CurveCount > 0) { if (toRotate.GetPlanarState() == PlanarState.Planar) { plane = toRotate.GetPlane(); path = toRotate.GetProjectedCurve(plane) as Path2D; } } } }
public override void OnDone() { // ist die Shift Taste gehalten, so werden Kopien gemacht, d.h. der die Elemente // des blocks werden eingefügt. Ansonsten werden die original-Objekte verändert // TODO: Feedback über Cursor bei Shift-Taste fehlt noch // TODO: die neuen oder veränderten Objekte sollten markiert sein. using (Frame.Project.Undo.UndoFrame) { ModOp m; if (!dis) { m = ModOp.Scale(base.BasePoint, faktor); // ein faktor für alle! } else { // 3 Faktoren für 3 Achsen m = ModOp.Scale(base.BasePoint, base.ActiveDrawingPlane.DirectionX, faktorX) * ModOp.Scale(base.BasePoint, base.ActiveDrawingPlane.DirectionY, faktorY) * ModOp.Scale(base.BasePoint, base.ActiveDrawingPlane.Normal, faktorZ); } if (!Precision.IsNull(Math.Abs(m.Determinant))) { if (((Frame.UIService.ModifierKeys & Keys.Shift) != 0) || copyObject) { GeoObjectList cloned = new GeoObjectList(); foreach (IGeoObject go in originals) { IGeoObject cl = go.Clone(); cl.Modify(m); cloned.Add(cl); } base.Frame.Project.GetActiveModel().Add(cloned); } else { originals.Modify(m); } } } base.ActiveObject = null; // damit es nicht gleich eingefügt wird base.OnDone(); }
static public bool canUseList(GeoObjectList selectedObjects) { Path toRotate = Path.Construct(); GeoObjectList clones = selectedObjects.CloneObjects(); if (selectedObjects.Count == 1) { if (selectedObjects[0] is Hatch) { return(true); } if (selectedObjects[0] is Face) { if ((selectedObjects[0] as Face).Surface is PlaneSurface) { return(true); } clones.Clear(); foreach (Edge edg in (selectedObjects[0] as Face).AllEdgesIterated()) { if (edg.Curve3D != null) { clones.Add(edg.Curve3D as IGeoObject); } } } } toRotate.Set(clones, false, Precision.eps); if (toRotate.CurveCount > 0) { if (toRotate.GetPlanarState() == PlanarState.UnderDetermined || toRotate.GetPlanarState() == PlanarState.Planar) { return(true); } } return(false); }
public Constr3DFaceExtrude(GeoObjectList selectedObjectsList) : this() { selectedMode = (selectedObjectsList != null); if (selectedMode) { GeoObjectList clonedList = selectedObjectsList.Clone(); GeoObjectList curves = new GeoObjectList(); for (int i = clonedList.Count - 1; i >= 0; --i) { if (clonedList[i] is ICurve) { curves.Add(clonedList[i]); clonedList.Remove(i); } } Plane pln; CompoundShape cs = CompoundShape.CreateFromList(curves, Precision.eps, out pln); if (cs != null && !cs.Empty) { // man konnte ein CompoundShape erzeugen, dann dieses zu Faces machen und verwenden for (int i = 0; i < cs.SimpleShapes.Length; i++) { PlaneSurface ps = new PlaneSurface(pln); Face toAdd = Face.MakeFace(ps, cs.SimpleShapes[i]); toAdd.CopyAttributes(curves[0]); clonedList.Add(toAdd); } this.selectedObjectsList = clonedList; } else { this.selectedObjectsList = selectedObjectsList.Clone(); } ListDefault(this.selectedObjectsList.Count); // setzt alle Listen auf gleiche Länge, Inhalte "null" } ; }
public Shell[] Read(string fileName) { List <Shell> res = new List <Shell>(); using (sr = new StreamReader(fileName)) // may throw exceptions like "file not found" etc. { char[] head = new char[5]; int read = sr.ReadBlock(head, 0, 5); if (read != 5) { throw new ApplicationException("cannot read from file"); } if (new string(head) == "solid") { isASCII = true; } else { isASCII = false; } } if (isASCII) { sr = new StreamReader(fileName); string title = sr.ReadLine(); } else { br = new BinaryReader(File.Open(fileName, FileMode.Open)); br.ReadBytes(80); uint nrtr = br.ReadUInt32(); } OctTree <Vertex> verticesOctTree = null; triangle tr; int cnt = 0; Set <Face> allFaces = new Set <Face>(); GeoObjectList dbgl = new GeoObjectList(); do { tr = GetNextTriangle(); if (tr == null) { break; } if (verticesOctTree == null) { verticesOctTree = new OctTree <Vertex>(new BoundingCube(tr.p1, tr.p2, tr.p3), 1e-6); } try { PlaneSurface ps = new PlaneSurface(tr.p1, tr.p2, tr.p3); Vertex v1 = VertexFromPoint(verticesOctTree, tr.p1); Vertex v2 = VertexFromPoint(verticesOctTree, tr.p2); Vertex v3 = VertexFromPoint(verticesOctTree, tr.p3); Edge e1 = Vertex.SingleConnectingEdge(v1, v2); if (e1 != null && e1.SecondaryFace != null) { } if (e1 == null || e1.SecondaryFace != null) { e1 = new Edge(Line.TwoPoints(v1.Position, v2.Position), v1, v2); } Edge e2 = Vertex.SingleConnectingEdge(v2, v3); if (e2 != null && e2.SecondaryFace != null) { } if (e2 == null || e2.SecondaryFace != null) { e2 = new Edge(Line.TwoPoints(v2.Position, v3.Position), v2, v3); } Edge e3 = Vertex.SingleConnectingEdge(v3, v1); if (e3 != null && e3.SecondaryFace != null) { } if (e3 == null || e3.SecondaryFace != null) { e3 = new Edge(Line.TwoPoints(v3.Position, v1.Position), v3, v1); } dbgl.Add(Line.TwoPoints(v1.Position, v2.Position)); dbgl.Add(Line.TwoPoints(v2.Position, v3.Position)); dbgl.Add(Line.TwoPoints(v3.Position, v1.Position)); Face fc = Face.Construct(); fc.Surface = ps; //Line2D l1 = new Line2D(ps.Plane.Project(tr.p1), ps.Plane.Project(tr.p2)); //Line2D l2 = new Line2D(ps.Plane.Project(tr.p2), ps.Plane.Project(tr.p3)); //Line2D l3 = new Line2D(ps.Plane.Project(tr.p3), ps.Plane.Project(tr.p1)); //if (e1.PrimaryFace == null) e1.SetPrimary(fc, l1, true); //else e1.SetSecondary(fc, l1, false); //if (e2.PrimaryFace == null) e2.SetPrimary(fc, l2, true); //else e2.SetSecondary(fc, l2, false); //if (e3.PrimaryFace == null) e3.SetPrimary(fc, l3, true); //else e3.SetSecondary(fc, l3, false); e1.SetFace(fc, e1.Vertex1 == v1); e2.SetFace(fc, e2.Vertex1 == v2); e3.SetFace(fc, e3.Vertex1 == v3); fc.Set(ps, new Edge[][] { new Edge[] { e1, e2, e3 } }); allFaces.Add(fc); ++cnt; } catch (ModOpException) { // empty triangle, plane construction failed } } while (tr != null); while (!allFaces.IsEmpty()) { Shell part = Shell.CollectConnected(allFaces); #if DEBUG // TODO: some mechanism to tell whether and how to reverse engineer the stl file double precision; if (numnum == 0) { precision = part.GetExtent(0.0).Size * 1e-5; } else { precision = Math.Pow(10, -numdec / (double)(numnum)); // numdec/numnum is average number of decimal places } part.ReconstructSurfaces(precision); #endif res.Add(part); } return(res.ToArray()); }
public void Add(IGeoObject toAdd, System.Drawing.Color color, int debugHint = 0) { if (toAdd != null) { ColorDef cd = new ColorDef(color.Name, color); if (toAdd is IColorDef) { (toAdd as IColorDef).ColorDef = cd; } toShow.Add(toAdd); } }
public GeoObjectList makeFaceDo(GeoObjectList selectedObjectsList, IFrame frame) { this.selectedObjectsList = selectedObjectsList.Clone(); ListDefault(selectedObjectsList.Count); // setzt alle Listen auf gleiche Länge, Inhalte "null" IGeoObject iGeoObjectSel; // IGeoObject iGeoObjectOrg; Boolean success = false; // hat er wenigstens eins gefunden GeoObjectList outList = new GeoObjectList(); // sammelt die gelungenen faces for (int i = 0; i < selectedObjectsList.Count; i++) // läuft über alle selektierten Objekte. Evtl nur eins bei Konstruktion { IGeoObject iGeoObjectTemp = null; // lokaler Merker iGeoObjectSel = selectedObjectsList[i]; // zur Vereinfachung geoObjectOrgList[i] = iGeoObjectSel; // zum Weglöschen des Originals in onDone ownerList[i] = iGeoObjectSel.Owner; // owner merken für löschen pathCreatedFromModelList[i] = null; faceList[i] = null; // Boolean VectorOrHeightTemp = VectorOrHeight; if (!(iGeoObjectSel is Face) && !(iGeoObjectSel is Shell)) { if ((iGeoObjectSel is ICurve)) { Path p = null; if (selectedObjectsList.Count == 1 && !(iGeoObjectSel as ICurve).IsClosed) { p = CADability.GeoObject.Path.CreateFromModel(iGeoObjectSel as ICurve, frame.ActiveView.Model, frame.ActiveView.Projection, true); } if (p == null) { // also nur Einzelelement if (iGeoObjectSel is Path) { // schon fertig p = iGeoObjectSel.Clone() as Path; } else { // Pfad aus Einzelobjekt machen: p = Path.Construct(); p.Set(new ICurve[] { iGeoObjectSel.Clone() as ICurve }); } } else { // CreateFromModel hat was zusammengesetzt if (p.IsClosed) { geoObjectOrgList[i] = null; // zum nicht Weglöschen des Originals in onDone pathCreatedFromModelList[i] = p; // kopie merken für onDone p = p.Clone() as Path; p.Flatten(); } } if (p.IsClosed) { // jetzt face machen iGeoObjectTemp = Make3D.MakeFace(p, frame.Project); } } } if (iGeoObjectTemp != null) { // also was geeignetes dabei iGeoObjectTemp.CopyAttributes(iGeoObjectSel as IGeoObject); faceList[i] = iGeoObjectTemp; // fertiger Körper in shapeList success = true; } } // for-Schleife über die Objekte der Liste if (success) { using (frame.Project.Undo.UndoFrame) { for (int i = 0; i < selectedObjectsList.Count; i++) // geht durch die komplette Liste { if (faceList[i] != null) // nur hier was machen! { outList.Add(faceList[i]); // die Guten sammeln frame.Project.GetActiveModel().Add(faceList[i]); // einfügen if (frame.GetBooleanSetting("Construct.3D_Delete2DBase", false)) { if (geoObjectOrgList[i] != null) // evtl. Einzelobjekt (Object oder Path) als Original rauslöschen { ownerList[i].Remove(geoObjectOrgList[i] as IGeoObject); } else { // die Einzelelemente des CreateFromModel identifizieren for (int j = 0; j < pathCreatedFromModelList[i].Count; ++j) { IGeoObject obj = null; if ((pathCreatedFromModelList[i].Curve(j) as IGeoObject).UserData.ContainsData("CADability.Path.Original")) { obj = (pathCreatedFromModelList[i].Curve(j) as IGeoObject).UserData.GetData("CADability.Path.Original") as IGeoObject; } if (obj != null && obj.Owner != null) { obj.Owner.Remove(obj); // löschen } } } } } } } return(outList); } return(null); }
private void ShowContextMenu(Point mousePoint, IView vw) { currentView = vw; GeoObjectList result = new GeoObjectList(); int pickRadius = soa.Frame.GetIntSetting("Select.PickRadius", 5); Projection.PickArea pa = vw.Projection.GetPickSpace(new Rectangle(mousePoint.X - pickRadius, mousePoint.Y - pickRadius, pickRadius * 2, pickRadius * 2)); IActionInputView pm = vw as IActionInputView; GeoObjectList fl = vw.Model.GetObjectsFromRect(pa, new Set <Layer>(pm.GetVisibleLayers()), PickMode.onlyFaces, null); // returns all the face under the cursor // in most cases there is only a single face, which is of interest, only when we have two solids with same or overlapping faces // and one of them is not selectable without also selecting the other, we want both. faces = new List <Face>(); shells = new List <Shell>(); // only Shells, which are not part of a Solid solids = new List <Solid>(); features = new List <IEnumerable <Face> >(); double delta = vw.Model.Extent.Size * 1e-4; double mindist = double.MaxValue; for (int i = 0; i < fl.Count; i++) { if (fl[i] is Face face) // this should always be the case { double z = face.Position(pa.FrontCenter, pa.Direction, 0); if (z < mindist) { if (z < mindist - delta) { faces.Clear(); } faces.Add(face); mindist = z; } } } HashSet <Edge> relevantEdges = new HashSet <Edge>(); for (int i = 0; i < faces.Count; i++) { relevantEdges.UnionWith(faces[i].AllEdges); if (faces[i].Owner is Shell shell) { if (shell.Owner is Solid sld) { if (!solids.Contains(sld)) { solids.Add(sld); } } else { if (!shells.Contains(shell)) { shells.Add(shell); } } } } for (int i = 0; i < faces.Count; i++) { if (faces[i].Owner is Shell shell) { for (int j = 0; j < faces[i].OutlineEdges.Length; j++) { Edge edg = faces[i].OutlineEdges[j]; if (edg.IsPartOfHole(edg.OtherFace(faces[i]))) { Face otherFace = edg.OtherFace(faces[i]); if (otherFace != null) { Edge[] hole = otherFace.GetHole(edg); List <Edge[]> loops = new List <Edge[]> { hole }; List <IEnumerable <Face> > lfeatures = new List <IEnumerable <Face> >(); List <IEnumerable <Face> > lids = new List <IEnumerable <Face> >(); HashSet <Face> startWith = new HashSet <Face>(); foreach (Edge edge in hole) { startWith.Add(edge.OtherFace(otherFace)); // all faces that are connected to the hole in "otherFace" } shell.FeaturesFromEdges(loops, lfeatures, lids, startWith); for (int k = 0; k < lfeatures.Count; k++) { if (lfeatures[k].Count() < shell.Faces.Length * 0.5) { features.Add(lfeatures[k]); } } } } } } } curves = vw.Model.GetObjectsFromRect(pa, new Set <Layer>(pm.GetVisibleLayers()), PickMode.onlyEdges, null); // returns edges and curves edges = new List <Edge>(); // we only accept edges, which belong to one of the selected faces for (int i = curves.Count - 1; i >= 0; --i) { if (curves[i].Owner is Edge edge) { if (relevantEdges.Contains(edge)) { edges.Add(edge); } else { double z = curves[i].Position(pa.FrontCenter, pa.Direction, 0); if (z - delta < mindist) { edges.Add(edge); // this is an edge in front of the closest face } } curves.Remove(i); } else { double z = curves[i].Position(pa.FrontCenter, pa.Direction, 0); if (z - delta > mindist) { curves.Remove(i); } } } // now we have curves, edges, faces, shells and solids (text, hatch, block, dimension not yet implemented) from the right click // we also need access to the already selected edges and faces to GeoObjectList selobj = soa.GetSelectedObjects(); HashSet <Edge> selectedEdges = new HashSet <Edge>(); HashSet <Face> selectedFaces = new HashSet <Face>(); foreach (IGeoObject go in selobj) { if (go is ICurve && go.Owner is Edge edg) { selectedEdges.Add(edg); } if (go is Face fc) { selectedFaces.Add(fc); } } List <MenuWithHandler> cm = new List <MenuWithHandler>(); Shell owningShell = null; if (edges.Count > 0) { owningShell = (edges[0].Owner as Face).Owner as Shell; } if (owningShell == null && faces.Count > 0) { owningShell = (faces[0].Owner as Shell); } if (owningShell == null && selectedFaces.Count > 0) { owningShell = selectedFaces.First().Owner as Shell; } if (owningShell == null && selectedEdges.Count > 0) { owningShell = (selectedEdges.First().Owner as Face).Owner as Shell; } if (owningShell != null) { for (int i = 0; i < features.Count; i++) { List <Face> featureI = new List <Face>(features[i]); MenuWithHandler mh = new MenuWithHandler("MenuId.Feature"); mh.OnSelected = (m, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(featureI.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; MenuWithHandler positionFeature = new MenuWithHandler("MenuId.Feature.Position"); MenuWithHandler nameFeature = new MenuWithHandler("MenuId.Feature.Name"); mh.SubMenus = new MenuWithHandler[] { positionFeature, nameFeature }; // this is very rudimentary. We have to provide a version of ParametricsDistanceAction, where you can select from and to object. Only axis is implemented Shell shell = featureI[0].Owner as Shell; GeoObjectList fa = shell.FeatureAxis; Line axis = null; foreach (IGeoObject geoObject in fa) { Face axisOf = geoObject.UserData.GetData("CADability.AxisOf") as Face; if (axisOf != null) { if (featureI.Contains(axisOf)) { axis = geoObject as Line; } } if (axis != null) { break; } } positionFeature.OnCommand = (menuId) => { ParametricsDistanceActionOld pd = new ParametricsDistanceActionOld(featureI, soa.Frame); soa.Frame.SetAction(pd); return(true); }; positionFeature.OnSelected = (menuId, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(featureI.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; nameFeature.OnCommand = (menuId) => { string name = shell.GetNewFeatureName(); shell.AddFeature(name, featureI); if (shell.Owner is Solid sld) { soa.SetSelectedObject(sld); IPropertyEntry toEdit = soa.Frame.ControlCenter.FindItem(name); if (toEdit != null) { List <IPropertyEntry> parents = new List <IPropertyEntry>(); if (toEdit != null) { IPropertyEntry p = toEdit; while ((p = p.Parent as IPropertyEntry) != null) { parents.Add(p); } IPropertyPage propertyPage = parents[parents.Count - 1].Parent as IPropertyPage; if (propertyPage != null) { for (int k = parents.Count - 1; k >= 0; --k) { propertyPage.OpenSubEntries(parents[k], true); } toEdit.StartEdit(false); } } } } return(true); }; nameFeature.OnSelected = (menuId, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(featureI.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; cm.Add(mh); } } for (int i = 0; i < curves.Count; i++) { // No implementation for simple curves yet. // We would need a logical connection structure as in vertex->edge->face->shell in 2d curves, which we currently do not have. Face faceWithAxis = (curves[i] as IGeoObject).UserData.GetData("CADability.AxisOf") as Face; if (faceWithAxis != null) { MenuWithHandler mh = new MenuWithHandler("MenuId.Axis"); mh.SubMenus = GetFacesSubmenus(faceWithAxis).ToArray(); mh.Target = this; IGeoObject curveI = curves[i] as IGeoObject; mh.OnSelected = (m, selected) => { currentMenuSelection.Clear(); currentMenuSelection.Add(curveI); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; cm.Add(mh); } } for (int i = 0; i < edges.Count; i++) { MenuWithHandler mh = new MenuWithHandler(); mh.ID = "MenuId.Edge." + i.ToString(); mh.Text = StringTable.GetString("MenuId.Edge", StringTable.Category.label); List <MenuWithHandler> lmh = new List <MenuWithHandler>(); MenuWithHandler selectMoreEdges = new MenuWithHandler("MenuId.SelectMoreEdges"); lmh.Add(selectMoreEdges); Edge edgeI = edges[i]; selectMoreEdges.OnCommand = (menuId) => { soa.SetSelectedObject(edgeI.Curve3D as IGeoObject); soa.OverwriteMode(PickMode.onlyEdges); return(true); }; lmh.AddRange(edges[i].GetContextMenu(soa.Frame)); mh.SubMenus = lmh.ToArray(); mh.Target = this; cm.Add(mh); } for (int i = 0; i < faces.Count; i++) { MenuWithHandler mh = new MenuWithHandler(); mh.ID = "MenuId.Face." + i.ToString(); mh.Text = StringTable.GetString("MenuId.Face", StringTable.Category.label); List <MenuWithHandler> lmh = new List <MenuWithHandler>(); MenuWithHandler selectMoreFaces = new MenuWithHandler("MenuId.SelectMoreFaces"); lmh.Add(selectMoreFaces); Face faceI = faces[i]; selectMoreFaces.OnCommand = (menuId) => { soa.SetSelectedObject(faceI); soa.OverwriteMode(PickMode.onlyFaces); return(true); }; lmh.AddRange(GetFacesSubmenus(faces[i])); if (owningShell != null) { double thickness = owningShell.GetGauge(faces[i], out HashSet <Face> frontSide, out HashSet <Face> backSide); if (thickness != double.MaxValue && frontSide.Count > 0) { MenuWithHandler gauge = new MenuWithHandler("MenuId.Gauge"); gauge.OnCommand = (menuId) => { ParametricsOffset po = new ParametricsOffset(frontSide, backSide, soa.Frame, thickness); soa.Frame.SetAction(po); return(true); }; gauge.OnSelected = (menuId, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(frontSide.ToArray()); currentMenuSelection.AddRange(backSide.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; lmh.Add(gauge); } int n = owningShell.GetFaceDistances(faces[i], out List <Face> distanceTo, out List <double> distance, out List <GeoPoint> pointsFrom, out List <GeoPoint> pointsTo); for (int j = 0; j < n; j++) { if (backSide == null || !backSide.Contains(distanceTo[j])) // this is not already used as gauge { HashSet <Face> capturedFaceI = new HashSet <Face>(new Face[] { faces[i] }); HashSet <Face> capturedDistTo = new HashSet <Face>(new Face[] { distanceTo[j] }); double capturedDistance = distance[j]; GeoPoint capturedPoint1 = pointsFrom[j]; GeoPoint capturedPoint2 = pointsTo[j]; GeoObjectList feedbackArrow = currentView.Projection.MakeArrow(pointsFrom[j], pointsTo[j], currentView.Projection.ProjectionPlane, Projection.ArrowMode.circleArrow); MenuWithHandler faceDist = new MenuWithHandler("MenuId.FaceDistance"); faceDist.OnCommand = (menuId) => { ParametricsDistanceAction pd = new ParametricsDistanceAction(capturedFaceI, capturedDistTo, capturedPoint1, capturedPoint2, soa.Frame); soa.Frame.SetAction(pd); return(true); }; faceDist.OnSelected = (menuId, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(capturedFaceI.ToArray()); currentMenuSelection.AddRange(capturedDistTo.ToArray()); currentMenuSelection.AddRange(feedbackArrow); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; lmh.Add(faceDist); } } } mh.SubMenus = lmh.ToArray(); mh.Target = this; cm.Add(mh); //cm.AddRange(GetFacesSubmenus(faces)); } for (int i = 0; i < faces.Count; i++) { if (faces[i].Owner is Shell shell) { Shell sh = shell.FeatureFromFace(faces[i]); } } for (int i = 0; i < edges.Count; i++) { if (edges[i].PrimaryFace.Owner is Shell shell) { //shell.FeatureFromEdges(edges[i].PrimaryFace); } } for (int i = 0; i < shells.Count; i++) { MenuWithHandler mh = new MenuWithHandler(); mh.ID = "MenuId.Shell." + i.ToString(); mh.Text = StringTable.GetString("MenuId.Shell", StringTable.Category.label); mh.SubMenus = shells[i].GetContextMenu(soa.Frame); mh.Target = this; cm.Add(mh); } for (int i = 0; i < solids.Count; i++) { MenuWithHandler mh = new MenuWithHandler(); mh.ID = "MenuId.Solid." + i.ToString(); mh.Text = StringTable.GetString("MenuId.Solid", StringTable.Category.label); mh.SubMenus = solids[i].GetContextMenu(soa.Frame); mh.Target = this; cm.Add(mh); } { // selection independent menu items MenuWithHandler mh = new MenuWithHandler(); mh.ID = "MenuId.Show"; mh.Text = StringTable.GetString("MenuId.Show", StringTable.Category.label); MenuWithHandler mhShowHidden = new MenuWithHandler(); mhShowHidden.ID = "MenuId.ShowHidden"; mhShowHidden.Text = StringTable.GetString("MenuId.ShowHidden", StringTable.Category.label); mhShowHidden.OnCommand = (menuId) => { foreach (IGeoObject geoObject in vw.Model) { if (geoObject.Layer != null && geoObject.Layer.Name == "CADability.Hidden") { Layer layer = geoObject.UserData.GetData("CADability.OriginalLayer") as Layer; if (layer != null) { geoObject.Layer = layer; } } } return(true); }; MenuWithHandler mhShowAxis = new MenuWithHandler(); mhShowAxis.ID = "MenuId.ShowAxis"; mhShowAxis.Text = StringTable.GetString("MenuId.ShowAxis", StringTable.Category.label); mhShowAxis.OnCommand = (menuId) => { bool isOn = false; foreach (IGeoObject geoObject in vw.Model) { Shell shell = null; if (geoObject is Solid solid) { shell = solid.Shells[0]; } else if (geoObject is Shell sh) { shell = sh; } if (shell != null && shell.FeatureAxis.Count > 0) { isOn = shell.FeatureAxis[0].IsVisible; break; } } using (vw.Canvas.Frame.Project.Undo.UndoFrame) { foreach (IGeoObject geoObject in vw.Model) { if (geoObject is Solid solid) { solid.ShowFeatureAxis = !isOn; } else if (geoObject is Shell shell) { shell.ShowFeatureAxis = !isOn; } } } return(true); }; mhShowAxis.OnUpdateCommand = (menuId, commandState) => { bool isOn = false; foreach (IGeoObject geoObject in vw.Model) { Shell shell = null; if (geoObject is Solid solid) { shell = solid.Shells[0]; } else if (geoObject is Shell sh) { shell = sh; } if (shell != null && shell.FeatureAxis.Count > 0) { isOn = shell.FeatureAxis[0].IsVisible; break; } } commandState.Checked = isOn; return(true); }; mh.SubMenus = new MenuWithHandler[] { mhShowHidden, mhShowAxis }; mh.Target = this; cm.Add(mh); } vw.SetPaintHandler(PaintBuffer.DrawingAspect.Select, new PaintView(OnRepaintSelect)); mousePoint.X += vw.DisplayRectangle.Width / 8; // find a better place for the menu position, using the extent of the objects vw.Canvas.ShowContextMenu(cm.ToArray(), mousePoint, ContextMenuCollapsed); }
private bool rotateOrg(bool openDraw) { if (selectedObjectsList == null || selectedObjectsList.Count == 0) { return(false); } IGeoObject selectedObject = null; blk = Block.Construct(); // as feedback object if (base.ActiveObject != null) { blk.CopyAttributes(base.ActiveObject); } // der block wird das neue aktive Objekt, er muss die Attribute tragen, weil sie später // wieder von ihm verlangt werden Boolean success = false; GeoPoint axisPointSav = axisPoint; GeoVector axisVectorSav = axisVector; updateOptional(); if (selectedObjectsList.Count > 1) { // maybe there are several curves in the list, then we try to make a path // and use only this path. No mixture of faces and paths possible List <ICurve> crvs = new List <ICurve>(); for (int i = 0; i < selectedObjectsList.Count; i++) { if (selectedObjectsList[i] is ICurve crv) { crvs.Add(crv); } } if (crvs.Count > 1) { Path path = Path.FromSegments(crvs, false); if (path != null) { selectedObjectsList.Clear(); selectedObjectsList.Add(path); } } } for (int i = 0; i < selectedObjectsList.Count; i++) { IGeoObject objectToRotate = null; // lokaler Merker geoObjectOrgList[i] = selectedObject; // zum Weglöschen des Originals in onDone selectedObject = selectedObjectsList[i]; ownerList[i] = selectedObject.Owner; // owner merken für löschen pathCreatedFromModelList[i] = null; shapeList[i] = null; if ((selectedObject is Face) || (selectedObject is Shell)) { // nur kopieren objectToRotate = selectedObject.Clone(); } else { if (selectedObject is ICurve selCurve) { Path p = null; if (!selCurve.IsClosed) { // trying to rotate an open curve: if the axis and the curve have a commonn plane close a path with the perpendicular foot points and axis segment Line axisLine = Line.TwoPoints(axisPoint, axisPoint + axisVector); if (Curves.GetCommonPlane(new ICurve[] { selCurve, axisLine }, out Plane commonPlane)) { Line l1 = Line.TwoPoints(selCurve.EndPoint, Geometry.DropPL(selCurve.EndPoint, axisPoint, axisVector)); Line l2 = Line.TwoPoints(Geometry.DropPL(selCurve.StartPoint, axisPoint, axisVector), selCurve.StartPoint); Line l3 = Line.TwoPoints(l1.EndPoint, l2.StartPoint); List <ICurve> closedPath = new List <ICurve>(); closedPath.Add(selCurve); if (l1.Length > Precision.eps) { closedPath.Add(l1); } if (l3.Length > Precision.eps) { closedPath.Add(l3); } if (l2.Length > Precision.eps) { closedPath.Add(l2); } p = Path.FromSegments(closedPath, true); // should always work p.Flatten(); } } else { p = Path.FromSegments(new ICurve[] { selCurve }, true); } if (p == null) { continue; // no path constructed } if ((p as ICurve).GetSelfIntersections().Length > 0) { continue; // not possible } if (!p.IsClosed) { continue; } // make a face from the closed pathe objectToRotate = Make3D.MakeFace(p, Frame.Project, true); } } if (objectToRotate != null) { // also was geeignetes dabei //if (angleOffsetRotation != 0.0) //{ // ModOp m = ModOp.Rotate(axisPoint, axisVector, new SweepAngle(angleOffsetRotation)); // iGeoObjectTemp.Modify(m); //} double sw = angleRotation; if (sw == 0.0) { sw = Math.PI * 2.0; } // IGeoObject shape = Make3D.MakeRevolution(iGeoObjectTemp, axisPoint, axisVector, sw, Frame.Project); IGeoObject shape = Make3D.Rotate(objectToRotate, new Axis(axisPoint, axisVector), sw, angleOffsetRotation, Frame.Project); if (shape != null) { shape.CopyAttributes(blk); shapeList[i] = shape; // fertiger Körper in shapeList blk.Add(shape); // resulting object base.FeedBack.AddSelected(objectToRotate); // zum Markieren des Ursprungsobjekts success = true; } } } axisPoint = axisPointSav; // im Fall nicht geschlossener Pfad und nichts bestimmt, werden diese Parameter oben verstellt axisVector = axisVectorSav; if (success) { base.ActiveObject = blk; // darstellen base.ShowActiveObject = true; return(true); } else { updateOptional(); base.ShowActiveObject = false; base.FeedBack.ClearSelected(); return(false); } }