コード例 #1
0
ファイル: SawingTechOperation.cs プロジェクト: presscad/CAM
        public override void BuildProcessing(ICommandGenerator generator)
        {
            const int CornerIndentIncrease = 5;
            var       techProcess          = (SawingTechProcess)TechProcess;
            var       curve        = ProcessingArea.GetCurve();
            var       thickness    = techProcess.Thickness.Value;
            var       toolDiameter = techProcess.Tool.Diameter;
            var       engineSide   = Side.None;
            double    offsetArc    = 0;
            double    angleA       = 0;

            if (techProcess.MachineType == MachineType.ScemaLogic)
            {
                AngleA = 0;
            }

            switch (curve)
            {
            case Arc arc:
                CalcArc(arc);
                break;

            case Line line:
                CalcLine(line);
                break;

            case Polyline polyline:
                CalcPolyline(polyline);
                break;

            default:
                throw new InvalidOperationException($"Кривая типа {curve.GetType()} не может быть обработана.");
            }

            var outerSideSign = OuterSide == Side.Left ^ curve is Line ? -1 : 1;
            var offsetCoeff   = Math.Tan(angleA) * outerSideSign;
            var depthCoeff    = 1 / Math.Cos(angleA);
            var toolThickness = techProcess.Tool.Thickness.Value * depthCoeff;
            var compensation  = (offsetArc + (engineSide == OuterSide ^ techProcess.MachineType == MachineType.Donatoni ? toolThickness : 0)) * outerSideSign;
            var shift         = angleA > 0 ? -thickness * offsetCoeff : 0;

            var sumIndent = CalcIndent(thickness) * (Convert.ToInt32(IsExactlyBegin) + Convert.ToInt32(IsExactlyEnd));

            if (sumIndent >= curve.Length())
            {
                if (AngleA != 0)
                {
                    throw new InvalidOperationException("Расчет намечания выполняется только при нулевом вертикальном угле.");
                }
                var point = Scheduling();
                var angle = BuilderUtils.CalcToolAngle((curve.EndPoint - curve.StartPoint).ToVector2d().Angle, engineSide);
                generator.Move(point.X, point.Y, angleC: angle);
                generator.Cutting(point.X, point.Y, point.Z, techProcess.PenetrationFeed);
                return;
            }

            var modes = SawingModes.ConvertAll(p => new CuttingMode {
                Depth = p.Depth, DepthStep = p.DepthStep, Feed = p.Feed
            });
            var passList = BuilderUtils.GetPassList(modes, thickness, !ProcessingArea.ObjectId.IsLine()).ToList();

            Curve toolpathCurve = null;

            foreach (var item in passList)
            {
                CreateToolpath(item.Key, compensation + shift + item.Key * offsetCoeff);
                if (generator.IsUpperTool)
                {
                    var point  = engineSide == Side.Right ^ (passList.Count() % 2 == 1) ? toolpathCurve.EndPoint : toolpathCurve.StartPoint;
                    var vector = Vector3d.ZAxis * (item.Key + generator.ZSafety);
                    if (angleA != 0)
                    {
                        vector = vector.RotateBy(outerSideSign * angleA, ((Line)toolpathCurve).Delta) * depthCoeff;
                    }
                    var p0     = point + vector;
                    var angleC = BuilderUtils.CalcToolAngle(toolpathCurve, point, engineSide);
                    generator.Move(p0.X, p0.Y, angleC: angleC, angleA: Math.Abs(AngleA));
                    if (techProcess.MachineType == MachineType.ScemaLogic)
                    {
                        generator.Command("28;;XYCZ;;;;;;", "Цикл");
                    }
                }
                generator.Cutting(toolpathCurve, item.Value, techProcess.PenetrationFeed, engineSide);
            }
            generator.Uplifting(Vector3d.ZAxis.RotateBy(outerSideSign * angleA, toolpathCurve.EndPoint - toolpathCurve.StartPoint) * (thickness + generator.ZSafety) * depthCoeff);

            if (!IsExactlyBegin || !IsExactlyEnd)
            {
                var gashCurve = curve.GetOffsetCurves(shift)[0] as Curve;
                if (!IsExactlyBegin)
                {
                    Acad.CreateGash(gashCurve, gashCurve.StartPoint, OuterSide, thickness * depthCoeff, toolDiameter, toolThickness);
                }
                if (!IsExactlyEnd)
                {
                    Acad.CreateGash(gashCurve, gashCurve.EndPoint, OuterSide, thickness * depthCoeff, toolDiameter, toolThickness);
                }
                gashCurve.Dispose();
            }

            // Local func ------------------------

            void CalcArc(Arc arc)
            {
                AngleA = 0;
                var startSide      = Math.Sign(Math.Cos(arc.StartAngle.Round(3)));
                var endSide        = Math.Sign(Math.Cos(arc.EndAngle.Round(3)));
                var cornersOneSide = Math.Sign(startSide * endSide);

                if (arc.TotalAngle.Round(3) > Math.PI && cornersOneSide > 0)
                {
                    throw new InvalidOperationException("Обработка дуги невозможна - дуга пересекает углы 90 и 270 градусов.");
                }

                if (cornersOneSide < 0) //  дуга пересекает углы 90 или 270 градусов
                {
                    if (techProcess.MachineType == MachineType.ScemaLogic)
                    {
                        throw new InvalidOperationException("Обработка дуги невозможна - дуга пересекает угол 90 или 270 градусов.");
                    }

                    engineSide = startSide > 0 ? Side.Left : Side.Right;
                }
                if (OuterSide == Side.Left)                                                         // внутренний рез дуги
                {
                    if (techProcess.MachineType == MachineType.Donatoni && engineSide != Side.Left) // подворот диска при вн. резе дуги
                    {
                        engineSide = Side.Right;
                        //var comp = arc.Radius - Math.Sqrt(arc.Radius * arc.Radius - thickness * (toolDiameter - thickness));
                        //AngleA = Math.Atan2(comp, thickness).ToDeg();

                        var R    = arc.Radius;
                        var t    = thickness;
                        var d    = toolDiameter;
                        var comp = (2 * R * t * t - Math.Sqrt(-d * d * d * d * t * t + 4 * d * d * R * R * t * t + d * d * t * t * t * t)) / (d * d - 4 * R * R);
                        AngleA = -Math.Atan2(comp, thickness).ToDeg();
                    }
                    else
                    {
                        offsetArc = arc.Radius - Math.Sqrt(arc.Radius * arc.Radius - thickness * (toolDiameter - thickness));
                    }
                }
                if (engineSide == Side.None)
                {
                    engineSide = (startSide + endSide) > 0 ? Side.Right : Side.Left;
                }
            }

            void CalcLine(Line line)
            {
                angleA     = AngleA.ToRad();
                engineSide = AngleA == 0 ? BuilderUtils.CalcEngineSide(line.Angle) : AngleA > 0 ? OuterSide : OuterSide.Opposite();
            }

            void CalcPolyline(Polyline polyline)
            {
                int sign = 0;

                for (int i = 0; i < polyline.NumberOfVertices; i++)
                {
                    var point = polyline.GetPoint3dAt(i);
                    var s     = Math.Sign(Math.Sin(polyline.GetTangent(point).Angle.Round(6)));
                    if (s == 0)
                    {
                        continue;
                    }
                    if (sign == 0)
                    {
                        sign = s;
                        continue;
                    }
                    var bulge = polyline.GetBulgeAt(i - 1);
                    if (bulge == 0)
                    {
                        bulge = polyline.GetBulgeAt(i);
                    }

                    if (s != sign)
                    {
                        if (techProcess.MachineType == MachineType.ScemaLogic)
                        {
                            throw new InvalidOperationException("Обработка полилинии невозможна - кривая пересекает углы 90 или 270 градусов.");
                        }
                        var side = sign > 0 ^ bulge < 0 ? Side.Left : Side.Right;
                        if (engineSide != Side.None)
                        {
                            if (engineSide != side)
                            {
                                throw new InvalidOperationException("Обработка полилинии невозможна.");
                            }
                        }
                        else
                        {
                            engineSide = side;
                        }
                        sign = s;
                    }
                    else
                    if (Math.Abs(bulge) > 1)
                    {
                        throw new InvalidOperationException("Обработка невозможна - дуга полилинии пересекает углы 90 и 270 градусов.");
                    }
                }
                if (engineSide == Side.None)
                {
                    engineSide = BuilderUtils.CalcEngineSide(polyline.GetTangent(polyline.StartPoint).Angle);
                }
            }

            void CreateToolpath(double depth, double offset)
            {
                toolpathCurve = curve.GetOffsetCurves(offset)[0] as Curve;
                toolpathCurve.TransformBy(Matrix3d.Displacement(-Vector3d.ZAxis * depth));
                if (!IsExactlyBegin && !IsExactlyEnd)
                {
                    return;
                }
                var indent = CalcIndent(depth * depthCoeff);

                switch (toolpathCurve)
                {
                case Line l:
                    if (IsExactlyBegin)
                    {
                        l.StartPoint = l.GetPointAtDist(indent);
                    }
                    if (IsExactlyEnd)
                    {
                        l.EndPoint = l.GetPointAtDist(l.Length - indent);
                    }
                    break;

                case Arc a:
                    var indentAngle = indent / ((Arc)curve).Radius;
                    if (IsExactlyBegin)
                    {
                        a.StartAngle = a.StartAngle + indentAngle;
                    }
                    if (IsExactlyEnd)
                    {
                        a.EndAngle = a.EndAngle - indentAngle;
                    }
                    break;

                case Polyline p:
                    if (IsExactlyBegin)
                    {
                        p.SetPointAt(0, p.GetPointAtDist(indent).ToPoint2d());
                    }
                    //p.StartPoint = p.GetPointAtDist(indent);
                    if (IsExactlyEnd)
                    {
                        //p.EndPoint = p.GetPointAtDist(p.Length - indent);
                        p.SetPointAt(p.NumberOfVertices - 1, p.GetPointAtDist(p.Length - indent).ToPoint2d());
                    }
                    break;
                }
                ;
            }

            double CalcIndent(double depth) => Math.Sqrt(depth * (toolDiameter - depth)) + CornerIndentIncrease;

            /// <summary>
            /// Расчет точки намечания
            /// </summary>
            Point3d Scheduling()
            {
                var vector = curve.EndPoint - curve.StartPoint;
                var depth  = thickness;
                var point  = Point3d.Origin;

                if (IsExactlyBegin && IsExactlyEnd)
                {
                    var l = vector.Length - 2 * CornerIndentIncrease;
                    depth = (toolDiameter - Math.Sqrt(toolDiameter * toolDiameter - l * l)) / 2;
                    point = curve.StartPoint + vector / 2;
                }
                else
                {
                    var indentVector = vector.GetNormal() * (Math.Sqrt(depth * (toolDiameter - depth)) + CornerIndentIncrease);
                    point = IsExactlyBegin ? curve.StartPoint + indentVector : curve.EndPoint - indentVector;
                    Acad.CreateGash(curve, IsExactlyBegin ? curve.EndPoint : curve.StartPoint, OuterSide, depth, toolDiameter, toolThickness, point);
                }
                return(point + vector.GetPerpendicularVector().GetNormal() * compensation - Vector3d.ZAxis * depth);
            }
        }
コード例 #2
0
        public override void BuildProcessing(MillingCommandGenerator generator)
        {
            var railBase    = TechProcess.Rail?.GetCurve() ?? new Line(Point3d.Origin, Point3d.Origin + Vector3d.XAxis * TechProcess.Length.Value);
            var profile     = (Profile ?? TechProcess.ProcessingArea[0]).GetCurve();
            var processSide = ChangeProcessSide ? 1 : -1;

            CreateProfile3D(profile, railBase, processSide);

            var rail = CreateDepartureRail(railBase, Departure);

            if (Delta != 0)
            {
                var profileOffset = (Curve)profile.GetOffsetCurves(Delta)[0];
                profile = profileOffset.EndPoint.GetAsVector().Length < profile.EndPoint.GetAsVector().Length
                    ? (Curve)profile.GetOffsetCurves(-Delta)[0]
                    : profileOffset;
                CreateProfile3D(profile, railBase, processSide);
            }
            var offsetSign = processSide * (railBase is Line ? 1 : -1);

            if (railBase.IsNewObject)
            {
                railBase.Dispose();
            }

            var side = BuilderUtils.CalcEngineSide(rail.GetFirstDerivative(0).GetAngleTo(Vector3d.XAxis));

            if (ChangeEngineSide)
            {
                side = SideExt.Opposite(side);
            }
            var isMinToolCoord = IsA90
                ? TechProcess.MachineType.Value != MachineType.ScemaLogic
                : side == Side.Right ^ TechProcess.MachineType.Value == MachineType.ScemaLogic ^ ChangeProcessSide;

            generator.CuttingFeed = CuttingFeed;
            generator.SmallFeed   = TechProcess.PenetrationFeed;
            generator.EngineSide  = side;

            Curve outletCurve = null;

            if (IsA90 && IsOutlet)
            {
                outletCurve = rail.GetOffsetCurves(TechProcess.ZSafety * offsetSign)[0] as Curve;
                var angleC = BuilderUtils.CalcToolAngle(outletCurve, outletCurve.StartPoint, side);
                generator.Move(outletCurve.StartPoint.X, outletCurve.StartPoint.Y, angleC: angleC, angleA: 90);
            }
            var angleA = IsA90 ? 90 : 0;
            var index  = IsA90 ? 1 : 0;

            var profilePoints = BuilderUtils.GetProcessPoints(profile, index, ProfileStep, TechProcess.Tool.Thickness.Value, isMinToolCoord, ProfileBegin, ProfileEnd, IsExactlyBegin, IsExactlyEnd, true);

            var profilePline = new Polyline();

            Enumerable.Range(0, profilePoints.Count).ForEach(i => profilePline.AddVertexAt(i, profilePoints[i], 0, 0, 0));

            var railLength = rail.Length();

            Acad.SetLimitProgressor((int)(railLength / LongStep));

            for (double dist = 0; dist < railLength; dist += LongStep)
            {
                Acad.ReportProgressor();

                var point     = rail.GetPointAtDist(dist);
                var angleC    = BuilderUtils.CalcToolAngle(rail, point, side);
                var passPline = CalcPassPline(rail, point, profilePline, processSide);

                generator.Cutting(passPline, CuttingFeed, TechProcess.PenetrationFeed, angleC: angleC, angleA: angleA);

                if (IsOutlet)
                {
                    if (IsA90)
                    {
                        var pt = outletCurve.GetClosestPoint(generator.ToolPosition.Point);
                        generator.Move(pt.X, pt.Y);
                    }
                    else
                    {
                        generator.Uplifting();
                    }
                }
            }
            rail.Dispose();
        }
コード例 #3
0
        public override void BuildProcessing(MillingCommandGenerator generator)
        {
            var railBase    = TechProcess.Rail?.GetCurve() ?? new Line(Point3d.Origin, Point3d.Origin + Vector3d.XAxis * TechProcess.Length.Value);
            var profile     = (Profile ?? TechProcess.ProcessingArea[0]).GetCurve();
            var processSide = ChangeEngineSide ? -1 : 1;

            CreateProfile3D(profile, railBase, 1);
            //var processSide = ChangeProcessSide ? -1 : 1;
            //CreateProfile3D(profile, railBase, processSide);

            var rail = CreateDepartureRail(railBase, Departure);

            if (Delta != 0)
            {
                var profileOffset = (Curve)profile.GetOffsetCurves(Delta)[0];
                profile = profileOffset.EndPoint.GetAsVector().Length < profile.EndPoint.GetAsVector().Length
                    ? (Curve)profile.GetOffsetCurves(-Delta)[0]
                    : profileOffset;
                CreateProfile3D(profile, railBase, processSide);
            }
            if (!(railBase is Line))
            {
                processSide *= -1;
            }
            if (railBase.IsNewObject)
            {
                railBase.Dispose();
            }

            var side = BuilderUtils.CalcEngineSide(rail.GetFirstDerivative(0).GetAngleTo(Vector3d.XAxis));

            if (ChangeEngineSide)
            {
                side = SideExt.Opposite(side);
            }
            var isMinToolCoord = IsA90
                ? TechProcess.MachineType.Value != MachineType.ScemaLogic
                : side == Side.Right ^ TechProcess.MachineType.Value == MachineType.ScemaLogic ^ ChangeProcessSide;

            generator.CuttingFeed = CuttingFeed;
            generator.SmallFeed   = TechProcess.PenetrationFeed;
            generator.EngineSide  = side;

            Curve outletCurve = null;

            if (IsA90 && IsOutlet)
            {
                outletCurve = rail.GetOffsetCurves(TechProcess.ZSafety * processSide)[0] as Curve;
                var angleC = BuilderUtils.CalcToolAngle(outletCurve, outletCurve.StartPoint, side);
                generator.Move(outletCurve.StartPoint.X, outletCurve.StartPoint.Y, angleC: angleC, angleA: 90);
            }
            var angleA = IsA90 ? 90 : 0;
            var index  = IsA90 ? 1 : 0;

            var points = BuilderUtils.GetProcessPoints(profile, index, StepPass, TechProcess.Tool.Thickness.Value, isMinToolCoord, FirstPass, LasttPass, IsExactlyBegin, IsExactlyEnd, IsProfileStep);

            foreach (var point in points)
            {
                var end   = Math.Max(point[1 - index], PenetrationEnd ?? double.MinValue);
                var count = 1;
                var penetrationStepCalc = 0D;
                if (PenetrationStep.GetValueOrDefault() > 0 && PenetrationBegin.GetValueOrDefault() > end)
                {
                    var allPenetration = PenetrationBegin.Value - end;
                    count = (int)Math.Ceiling(allPenetration / PenetrationStep.Value);
                    penetrationStepCalc = allPenetration / count;
                }
                if (IsA90 && IsOutlet && generator._isEngineStarted)
                {
                    generator.Transition(z: point[index]);
                }

                var coords = Enumerable.Range(1, count).Select(p => end + (count - p) * penetrationStepCalc).ToList();
                if (IsA90)
                {
                    coords.ForEach(p => generator.Cutting(rail, processSide * p, point[index], angleA: angleA));
                }
                else
                {
                    coords.ForEach(p => generator.Cutting(rail, processSide * point[index], p, angleA: angleA));
                }

                if (IsOutlet)
                {
                    if (IsA90)
                    {
                        var pt = outletCurve.GetClosestPoint(generator.ToolPosition.Point);
                        generator.Move(pt.X, pt.Y);
                    }
                    else
                    {
                        generator.Uplifting();
                    }
                }
            }
            rail.Dispose();
        }
コード例 #4
0
        public void BuildProcessingOld(MillingCommandGenerator generator)
        {
            var sectionProfile = (SectionProfileTechProcess)TechProcess;
            var toolThickness  = TechProcess.Tool.Thickness.Value;

            var rail = sectionProfile.Rail != null?sectionProfile.Rail.GetCurve() as Line : new Line(Point3d.Origin, new Point3d(sectionProfile.Length.Value, 0, 0));

            var railVector  = rail.Delta.GetNormal();
            var passVector  = rail.Delta;
            var crossVector = railVector.RotateBy(-Math.PI / 2, Vector3d.ZAxis);
            var startPass   = rail.StartPoint;
            var shift       = TechProcess.MachineType == MachineType.Donatoni ^ BuilderUtils.CalcEngineSide(rail.Angle) == Side.Left ? toolThickness : 0;

            if (rail.IsNewObject)
            {
                rail.Dispose();
            }

            var profile = sectionProfile.ProcessingArea[0].GetCurve() as Polyline;

            if (profile == null)
            {
                throw new Exception("Профиль должен быть полилинией");
            }

            if (Delta != 0)
            {
                profile = (Polyline)profile.GetOffsetCurves(Delta)[0];
            }

            var endX          = Math.Max(profile.StartPoint.X, profile.EndPoint.X);
            var profilePoints = profile.GetPolylineFitPoints(ProfileStep).Select(p => new Point2d(endX - p.X, p.Y)).ToList();

            if (profilePoints[0].X > Consts.Epsilon)
            {
                profilePoints.Reverse();
            }
            profilePoints = profilePoints
                            .TakeWhile(p => p.X < toolThickness)
                            .Select(p => p - Vector2d.XAxis * toolThickness)
                            .Concat(profilePoints)
                            .ToList();
            var passPoints = profilePoints.Select((p, i) =>
            {
                var y = p.Y;
                for (int j = i + 1; j < profilePoints.Count && profilePoints[j].X - profilePoints[i].X < toolThickness; j++)
                {
                    if (profilePoints[j].Y > y)
                    {
                        y = profilePoints[j].Y;
                    }
                }
                return(new Point2d(p.X, y));
            })
                             .ToList();

            if (Departure > 0)
            {
                passPoints.Insert(0, new Point2d(-Departure, passPoints.First().Y));
                passPoints.Add(new Point2d(passPoints.Last().X + Departure, passPoints.Last().Y));
            }

            var sp = startPass + crossVector * (passPoints[0].X + shift) + passPoints[0].Y * Vector3d.ZAxis;

            generator.Move(sp.X, sp.Y, angleC: BuilderUtils.CalcToolAngle(railVector.GetAngleTo(Vector3d.XAxis)));

            var passPointsDirect = new List <Point2d>[2] {
                passPoints, Enumerable.Reverse(passPoints).ToList()
            };
            int direct = 0;

            Acad.SetLimitProgressor((int)(passVector.Length / LongStep));
            for (double x = 0; x < passVector.Length; x += LongStep)
            {
                Acad.ReportProgressor();
                passPointsDirect[direct].ForEach(p => generator.GCommand(CommandNames.Cutting, 1, point: startPass + crossVector * (p.X + shift) + p.Y * Vector3d.ZAxis + x * railVector, feed: CuttingFeed));
                direct = 1 - direct;
            }
        }