Esempio n. 1
0
        private void generateMovement(MachineState state, Point3D lastPosition, ToolPath result)
        {
            var startPosition = lastPosition;
            var endPosition   = state.CurrentPosition;

            switch (state.MotionMode)
            {
            case MotionMode.IsLinear:
            case MotionMode.IsLinearRapid:
                //for now aproximate by a simple line
                result.AddLine(endPosition, state);
                break;

            case MotionMode.IsCircularCW:
                addCircularApproximation(result, state, startPosition, endPosition, clockwise: true);
                break;

            case MotionMode.IsCircularCCW:
                addCircularApproximation(result, state, startPosition, endPosition, clockwise: false);
                break;


            default:
                throw new NotImplementedException();
            }
        }
Esempio n. 2
0
        private void addCircularApproximation(ToolPath result, MachineState state, Point3D startPosition, Point3D endPosition, bool clockwise)
        {
            if (state.PlaneSelectionMode != PlaneSelectionMode.XY)
            {
                throw new NotImplementedException();
            }

            //if (state.DistanceMode != DistanceMode.Relative)
            //TODO check specification properly regarding IJK behaviour - it seems inconsistent

            Point3D centerPoint;

            if (state.BufferI.HasValue)
            {
                var i = state.BufferI.Value;
                var j = state.BufferJ.Value;
                centerPoint = new Point3D(startPosition.X + i, startPosition.Y + j, startPosition.Z); //TODO this changes with selected plane
            }
            else
            {
                var inputRadius = state.BufferR.Value;
                // Negative R is g-code-alese for "I want a circle with more than 180 degrees of travel" (go figure!),
                // even though it is advised against ever generating such circles in a single line of g-code. By
                // inverting the sign of h_x2_div_d the center of the circles is placed on the opposite side of the line of
                // travel and thus we get the unadvisably long arcs as prescribed.

                var x1 = startPosition.X;
                var y1 = startPosition.Y;
                var x2 = endPosition.X;
                var y2 = endPosition.Y;
                var q  = Math.Sqrt(Math.Pow((x2 - x1), 2) + Math.Pow((y2 - y1), 2));

                var y3 = (y1 + y2) / 2;

                var x3 = (x1 + x2) / 2;

                var basex = Math.Sqrt(Math.Pow(inputRadius, 2) - Math.Pow((q / 2), 2)) * (y1 - y2) / q; //calculate once
                var basey = Math.Sqrt(Math.Pow(inputRadius, 2) - Math.Pow((q / 2), 2)) * (x2 - x1) / q; //calculate once

                var centerx1 = x3 + basex;                                                              //center x of circle 1
                var centery1 = y3 + basey;                                                              //center y of circle 1
                var centerx2 = x3 - basex;                                                              //center x of circle 2
                var centery2 = y3 - basey;                                                              //center y of circle 2

                //TODO negative radius and center selection
                centerPoint = new Point3D(centerx1, centery1, startPosition.Z);
            }

            var radius  = (startPosition - centerPoint).Length;
            var radius2 = (endPosition - centerPoint).Length;

            if (Math.Abs(radius - radius2) > _precision)
            {
                throw new NotSupportedException("Invalid arc detected");
            }

            var totalC     = (startPosition - endPosition).Length;
            var totalAngle = 2 * Math.Asin(totalC / 2 / radius);
            var stepAngle  = 2 * Math.Acos(1 - _precision / radius);

            var initialAngle = Math.Atan2(startPosition.Y - centerPoint.Y, startPosition.X - centerPoint.X); //REALLY, the coordinates are reversed
            var finalAngle   = Math.Atan2(endPosition.Y - centerPoint.Y, endPosition.X - centerPoint.X);

            var pi2 = Math.PI * 2;

            initialAngle = (initialAngle + pi2) % pi2;
            finalAngle   = (finalAngle + pi2) % pi2;

            double direction;

            if (clockwise)
            {
                direction = -1.0;
                if (initialAngle < finalAngle)
                {
                    //rotating clockwise == subtract steps from initial angle
                    initialAngle += pi2;
                }
            }
            else
            {
                direction = 1.0;
                if (initialAngle > finalAngle)
                {
                    //rotating ccw == add steps to initial angle
                    initialAngle -= pi2;
                }
            }


            totalAngle = Math.Abs(finalAngle - initialAngle);



            var segmentCount = Math.Ceiling(totalAngle / stepAngle);

            var lastPosition = startPosition;

            for (var segmentIndex = 1; segmentIndex < segmentCount; ++segmentIndex)
            {
                var actualAngle = initialAngle + direction * totalAngle * segmentIndex / segmentCount;
                var x           = Math.Cos(actualAngle) * radius;
                var y           = Math.Sin(actualAngle) * radius;

                var nextPosition = new Point3D();
                nextPosition.X = centerPoint.X + x;
                nextPosition.Y = centerPoint.Y + y;
                nextPosition.Z = centerPoint.Z; //TODO this changes with plane selection
                result.AddLine(nextPosition, state);

                lastPosition = nextPosition;
            }
            result.AddLine(endPosition, state);
        }