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 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; } } } }
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); }
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); } }