コード例 #1
0
 private void CollectConnectedFillets(Face face, HashSet <Face> connectedFillets)
 {
     if (!connectedFillets.Contains(face))
     {
         connectedFillets.Add(face);
         if (face.Surface is ISurfaceOfArcExtrusion extrusion)
         {
             foreach (Edge edge in face.OutlineEdges)
             {
                 Face otherFace = edge.OtherFace(face);
                 if (otherFace.IsFillet() && otherFace.Surface is ISurfaceOfArcExtrusion otherExtrusion && Precision.IsEqual(extrusion.Radius, otherExtrusion.Radius))
                 {
                     // if (edge.Curve2D(face).DirectionAt(0.5).IsMoreHorizontal == extrusion.ExtrusionDirectionIsV && otherFace.Surface is ISurfaceOfArcExtrusion arcExtrusion)
                     {
                         CollectConnectedFillets(otherFace, connectedFillets);
                     }
                 }
                 else if (otherFace.Surface is SphericalSurface ss && Precision.IsEqual(ss.RadiusX, extrusion.Radius))
                 {
                     CollectConnectedFillets(otherFace, connectedFillets);
                 }
             }
         }
コード例 #2
0
ファイル: RuledSurface.cs プロジェクト: SOFAgh/CADability
        /// <summary>
        /// Overrides <see cref="CADability.GeoObject.ISurfaceImpl.GetPlaneIntersection (PlaneSurface, double, double, double, double, double)"/>
        /// </summary>
        /// <param name="pl"></param>
        /// <param name="umin"></param>
        /// <param name="umax"></param>
        /// <param name="vmin"></param>
        /// <param name="vmax"></param>
        /// <param name="precision"></param>
        /// <returns></returns>
        public override IDualSurfaceCurve[] GetPlaneIntersection(PlaneSurface pl, double umin, double umax, double vmin, double vmax, double precision)
        {
            if (firstCurve is Line && secondCurve is Line)
            {
                if (Precision.IsPerpendicular(firstCurve.StartDirection, pl.Normal, false) &&
                    Precision.IsPerpendicular(secondCurve.StartDirection, pl.Normal, false))
                {   // eine Ebene, die zu beiden Linien parallel ist
                    GeoPoint sp1, ep1, sp2, ep2;
                    sp1 = firstCurve.PointAt(umin);
                    ep1 = secondCurve.PointAt(umin);
                    sp2 = firstCurve.PointAt(umax);
                    ep2 = secondCurve.PointAt(umax);
                    GeoPoint2D[] ip1 = pl.GetLineIntersection(sp1, ep1 - sp1);
                    GeoPoint2D[] ip2 = pl.GetLineIntersection(sp2, ep2 - sp2);
                    if (ip1.Length == 1 && ip2.Length == 1)
                    {
                        GeoPoint sp   = pl.PointAt(ip1[0]);
                        GeoPoint ep   = pl.PointAt(ip2[0]);
                        double   v    = Geometry.LinePar(sp1, ep1, sp);
                        Line     line = Line.Construct();
                        line.SetTwoPoints(sp, ep);
                        DualSurfaceCurve dsc = new DualSurfaceCurve(line, this, new Line2D(new GeoPoint2D(umin, v), new GeoPoint2D(umax, v)),
                                                                    pl, new Line2D(ip1[0], ip2[0]));
                        return(new IDualSurfaceCurve[] { dsc });
                    }
                }
            }
            if (firstCurve is Ellipse && secondCurve is Ellipse)
            {
                Ellipse e1 = firstCurve as Ellipse;
                Ellipse e2 = secondCurve as Ellipse;
                if (Precision.SameDirection(pl.Normal, e1.Plane.Normal, false) && Precision.SameDirection(pl.Normal, e2.Plane.Normal, false))
                {
                    if (e1.IsCircle && e2.IsCircle)
                    {
                        GeoPoint sp1, ep1, sp2, ep2, spm, epm;
                        sp1 = firstCurve.PointAt(umin);
                        ep1 = secondCurve.PointAt(umin);
                        sp2 = firstCurve.PointAt(umax);
                        ep2 = secondCurve.PointAt(umax);
                        spm = firstCurve.PointAt((umin + umax) / 2.0);
                        epm = secondCurve.PointAt((umin + umax) / 2.0);
                        GeoPoint2D[] ip1 = pl.GetLineIntersection(sp1, ep1 - sp1);
                        GeoPoint2D[] ip2 = pl.GetLineIntersection(sp2, ep2 - sp2);
                        GeoPoint2D[] ipm = pl.GetLineIntersection(spm, epm - spm);
                        if (ip1.Length == 1 && ip2.Length == 1 && ipm.Length == 1)
                        {
                            Ellipse e3 = Ellipse.Construct();
                            e3.SetArc3Points(pl.PointAt(ip1[0]), pl.PointAt(ipm[0]), pl.PointAt(ip2[0]), pl.Plane);
                            double           v   = Geometry.LinePar(sp1, ep1, pl.PointAt(ip1[0]));
                            DualSurfaceCurve dsc = new DualSurfaceCurve(e3, this, new Line2D(new GeoPoint2D(umin, v), new GeoPoint2D(umax, v)),
                                                                        pl, e3.GetProjectedCurve(pl.Plane));
                            return(new IDualSurfaceCurve[] { dsc });
                        }
                    }
                }
            }
            PlanarState ps1 = firstCurve.GetPlanarState();
            PlanarState ps2 = secondCurve.GetPlanarState();

            if ((ps1 == PlanarState.UnderDetermined || ps1 == PlanarState.Planar) && (ps2 == PlanarState.UnderDetermined || ps2 == PlanarState.Planar))
            {
                if (Precision.IsPerpendicular(firstCurve.StartDirection, pl.Normal, false) && Precision.IsPerpendicular(secondCurve.StartDirection, pl.Normal, false))
                {   // beide Kurven sind eben und parallel zur Schnittebene, wir haben also ein festes v und somit eine Zwischenkurve
                    GeoPoint         ip  = pl.Plane.Intersect(firstCurve.StartPoint, secondCurve.StartPoint - firstCurve.StartPoint);
                    double           v   = Geometry.LinePar(firstCurve.StartPoint, secondCurve.StartPoint, ip);
                    ICurve           cv  = FixedV(v, umin, umax);
                    DualSurfaceCurve dsc = new DualSurfaceCurve(cv, this, new Line2D(new GeoPoint2D(umin, v), new GeoPoint2D(umax, v)),
                                                                pl, cv.GetProjectedCurve(pl.Plane));
                    return(new IDualSurfaceCurve[] { dsc });
                }
            }
            return(base.GetPlaneIntersection(pl, umin, umax, vmin, vmax, precision));
        }
コード例 #3
0
        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);
        }
コード例 #4
0
 private void GetDistanceVector(out GeoPoint startPoint, out GeoPoint endPoint)
 {
     startPoint = endPoint = GeoPoint.Invalid;
     if (fromHere is GeoPoint point1 && toHere is GeoPoint point2)
     {   // I think, all other cases should be eliminated
         startPoint = point1;
         endPoint   = point2;
         return;
     }
     if (fromHere is Vertex vtx)
     {
         if (toHere is Vertex vtx2)
         {
             startPoint = vtx.Position;
             endPoint   = vtx2.Position;
             return;
         }
         else if (toHere is Edge edge2)
         {
             double pos = edge2.Curve3D.PositionOf(vtx.Position);
             if (pos >= -1e-6 && pos <= 1 + 1e-6)
             {
                 startPoint = vtx.Position;
                 endPoint   = edge2.Curve3D.PointAt(pos);
                 return;
             }
         }
         else if (toHere is Face fc2)
         {
             GeoPoint2D[] fps = fc2.Surface.PerpendicularFoot(vtx.Position);
             if (fps != null && fps.Length > 0)
             {
                 endPoint = startPoint = vtx.Position;
                 double minDist = double.MaxValue;
                 for (int i = 0; i < fps.Length; i++)
                 {
                     GeoPoint ep = fc2.Surface.PointAt(fps[i]);
                     double   d  = ep | startPoint;
                     if (d < minDist)
                     {
                         minDist  = d;
                         endPoint = ep;
                     }
                 }
                 return;
             }
         }
     }
     else if (fromHere is Edge edge)
     {
         if (toHere is Vertex vtx2)
         {
             double pos = edge.Curve3D.PositionOf(vtx2.Position);
             if (pos >= -1e-6 && pos <= 1 + 1e-6)
             {
                 endPoint   = vtx2.Position;
                 startPoint = edge.Curve3D.PointAt(pos);
                 return;
             }
         }
         else if (toHere is Edge edge2)
         {
             if (edge.Curve3D is Line l1 && edge2.Curve3D is Line l2)
             {
                 if (Precision.SameDirection(l1.StartDirection, l2.StartDirection, false))
                 {   // two parallel lines
                     double spos = Geometry.LinePar(l1.StartPoint, l1.EndPoint, l2.StartPoint);
                     double epos = Geometry.LinePar(l1.StartPoint, l1.EndPoint, l2.EndPoint);
                     if (epos < spos)
                     {
                         Hlp.Swap(ref spos, ref epos);
                     }
                     if (epos < 0)
                     {
                         spos = (epos + 0.0) / 2.0;
                         epos = 0.0;
                     }
                     else if (spos > 1)
                     {
                         epos = (spos + 1.0) / 2.0;
                         spos = 1.0;
                     }
                     else
                     {
                         spos = Math.Max(0.0, spos);
                         epos = Math.Min(epos, 1.0);
                     }
                     startPoint = Geometry.LinePos(l1.StartPoint, l1.EndPoint, (spos + epos) / 2.0);
                     endPoint   = Geometry.DropPL(startPoint, l2.StartPoint, l2.EndPoint);
                     return;
                 }
                 else
                 {   // two skewed lines
                     Geometry.ConnectLines(l1.StartPoint, l1.StartDirection, l2.StartPoint, l2.StartDirection, out double pos1, out double pos2);
                     startPoint = Geometry.LinePos(l1.StartPoint, l1.EndPoint, pos1);
                     endPoint   = Geometry.LinePos(l2.StartPoint, l2.EndPoint, pos2);
                     return;
                 }
             }
             // more cases ...
         }
         else if (toHere is Face fc2)
         {
             // to fill out
         }
     }
     else if (fromHere is Face face)
     {
         // to fill out
     }
 }