示例#1
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// If we fill a shape with the aperture at the current coordinates. This
        /// simulates the aperture flash of a Gerber plotter
        /// </summary>
        /// <param name="graphicsObj">a graphics object to draw on</param>
        /// <param name="workingBrush">a brush to draw with</param>
        /// <param name="x1">the x center value</param>
        /// <param name="y1">the y center value</param>
        /// <returns>z success, nz fail</returns>
        public override void FlashApertureForGerberPlot(GerberFileStateMachine stateMachine, Graphics graphicsObj, Brush workingBrush, float x1, float y1)
        {
            int hDia;

            if (graphicsObj == null)
            {
                return;
            }
            if (workingBrush == null)
            {
                return;
            }
            if (stateMachine == null)
            {
                return;
            }

            // scale the outside diameter
            int circleDiameter = (int)Math.Round((OutsideDimension * stateMachine.IsoPlotPointsPerAppUnit));

            // do we need to draw in the hole?
            if (HoleDiameter > 0)
            {
                // yes we do, do it this way
                hDia = (int)Math.Round((this.HoleDiameter * stateMachine.IsoPlotPointsPerAppUnit));
                MiscGraphicsUtils.FillPolygonCenteredOnPoint(graphicsObj, workingBrush, x1, y1, NumSides, circleDiameter, DegreesRotation, hDia);
            }
            else
            {
                // no we do not. Do it this way
                MiscGraphicsUtils.FillPolygonCenteredOnPoint(graphicsObj, workingBrush, x1, y1, NumSides, circleDiameter, DegreesRotation);
            }
            return;
        }
示例#2
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Performs the action the plot requires based on the current context
        /// </summary>
        /// <param name="graphicsObj">a graphics object on which to plot</param>
        /// <param name="stateMachine">the gcode plot state machine</param>
        /// <param name="errorString">the error string we return on fail</param>
        /// <param name="errorValue">the error value we return on fail, z success, nz fail </param>
        /// <param name="wantEndPointMarkers">if true we draw the endpoints of the gcodes
        /// in a different color</param>
        /// <returns>an enum value indicating what next action to take</returns>
        public override PlotActionEnum PerformPlotGCodeAction(Graphics graphicsObj, GCodeFileStateMachine stateMachine, bool wantEndPointMarkers, ref int errorValue, ref string errorString)
        {
            Brush workingBrush = null;

            if (stateMachine == null)
            {
                errorValue  = 999;
                errorString = "PerformPlotGCodeAction (Line) stateMachine == null";
                return(PlotActionEnum.PlotAction_FailWithError);
            }

            // we only plot this on cuts or touchdowns
            if (((zMoveHeight == GCodeZMoveHeightEnum.GCodeZMoveHeight_ZCoordForCut) ||
                 (zMoveHeight == GCodeZMoveHeightEnum.GCodeZMoveHeight_ZCoordForAlt1Cut)) == false)
            {
                return(PlotActionEnum.PlotAction_Continue);
            }
            // if the drill width <=0 we do not plot
            if (drillDiameter <= 0)
            {
                return(PlotActionEnum.PlotAction_Continue);
            }

            // get the brush
            workingBrush = stateMachine.PlotBorderBrush;

            // now draw in a circle of appropriate diameter
            MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x0, y0, drillDiameter, drillDiameter);

            return(PlotActionEnum.PlotAction_Continue);
        }
示例#3
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// If we fill a shape with the aperture at the current coordinates. This
        /// simulates the aperture flash of a Gerber plotter
        /// </summary>
        /// <param name="graphicsObj">a graphics object to draw on</param>
        /// <param name="workingBrush">a brush to draw with</param>
        /// <param name="x1">the x center value</param>
        /// <param name="y1">the y center value</param>
        /// <returns>z success, nz fail</returns>
        public override void FlashApertureForGerberPlot(GerberFileStateMachine stateMachine, Graphics graphicsObj, Brush workingBrush, float x1, float y1)
        {
            int hDia;

            if (graphicsObj == null)
            {
                return;
            }
            if (workingBrush == null)
            {
                return;
            }
            if (stateMachine == null)
            {
                return;
            }

            int circleDiameter = (int)Math.Round((this.outerDiameter * stateMachine.IsoPlotPointsPerAppUnit));

            // do we need to draw in the hole?
            if (HoleDiameter > 0)
            {
                // yes we do, do it this way
                hDia = (int)Math.Round((this.HoleDiameter * stateMachine.IsoPlotPointsPerAppUnit));
                MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x1, y1, circleDiameter, circleDiameter, hDia);
            }
            else
            {
                // no we do not. Do it this way
                MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x1, y1, circleDiameter, circleDiameter);
            }
            return;
        }
示例#4
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets the horizontal Right Center point. Note due to rotations this point may not be
        /// the actual Right Center point (or horizontal) - you have to check
        /// </summary>
        /// <param name="varArray">the array to get the numbered variables from</param>
        /// <param name="xyCompInPlotCoords">the xy compensation in plot coordinates (Gerber not screen coords)</param>
        /// <param name="wantInverseXYComp">if true we apply the xyComp in inverse</param>
        public PointF GetRightCenterCoord(GerberMacroVariableArray varArray, float xyCompInPlotCoords, bool wantInverseXYComp)
        {
            float workingXCenterCoord    = GetXCenterCoord(varArray);
            float workingYCenterCoord    = GetYCenterCoord(varArray);
            float workingDegreesRotation = GetDegreesRotation(varArray);
            float workingWidth           = GetWidth(varArray);
            //float workingHeight = GetHeight(varArray);

            // calc this now
            float xCoord = 0;

            if (wantInverseXYComp == true)
            {
                xCoord = workingXCenterCoord + (workingWidth / 2) - xyCompInPlotCoords;
            }
            else
            {
                xCoord = workingXCenterCoord + (workingWidth / 2) + xyCompInPlotCoords;
            }
            float yCoord = workingYCenterCoord;

            // do we have a rotation
            if (workingDegreesRotation != 0)
            {
                PointF pointToRotate = new PointF(xCoord, yCoord);
                PointF centerPoint   = new PointF(workingXCenterCoord, workingYCenterCoord);
                // do the math and return
                return(MiscGraphicsUtils.RotatePointAboutPointByDegrees(centerPoint, workingDegreesRotation, pointToRotate));
            }
            else
            {
                // no just return the existing value
                return(new PointF(xCoord, yCoord));
            }
        }
示例#5
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Performs the action the plot requires based on the current context
        /// </summary>
        /// <param name="graphicsObj">a graphics object on which to plot</param>
        /// <param name="stateMachine">the excellon plot state machine</param>
        /// <param name="errorString">the error string we return on fail</param>
        /// <param name="errorValue">the error value we return on fail, z success, nz fail </param>
        /// <returns>an enum value indicating what next action to take</returns>
        public override PlotActionEnum PerformPlotExcellonAction(Graphics graphicsObj, ExcellonFileStateMachine stateMachine, ref int errorValue, ref string errorString)
        {
            int x0 = GetIsoPlotCoordOriginCompensated_X(stateMachine);
            int y0 = GetIsoPlotCoordOriginCompensated_Y(stateMachine);

            // G00 rapid move tool head to the xCoord, yCoord
            stateMachine.LastXCoord     = XCoord;
            stateMachine.LastYCoord     = YCoord;
            stateMachine.LastPlotXCoord = x0;
            stateMachine.LastPlotYCoord = y0;
            // record locally
            lastPlotXCoordEnd = x0;
            lastPlotYCoordEnd = y0;

            // set the drill width
            float workingDrillWidth = stateMachine.LastDrillWidth * stateMachine.IsoPlotPointsPerAppUnit;

            // remember this
            LastDrillWidth = stateMachine.LastDrillWidth;

            MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, stateMachine.ExcellonHoleBrush, x0, y0, workingDrillWidth, workingDrillWidth);

            errorValue  = 0;
            errorString = "Successful End";
            return(PlotActionEnum.PlotAction_Continue);
        }
示例#6
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets the LR point. Note due to rotations this point may not be
        /// the actual LR point - you have to check
        /// </summary>
        /// <param name="varArray">the array to get the numbered variables from</param>
        public PointF GetLRCoord(GerberMacroVariableArray varArray)
        {
            PointF centerPoint = GetCenterPoint(varArray);

            float workingXCenterCoord    = centerPoint.X;
            float workingYCenterCoord    = centerPoint.Y;;
            float workingDegreesRotation = GetDegreesRotation(varArray);
            float workingWidth           = GetWidth(varArray);
            float workingHeight          = GetLineLength(varArray);

            // calc this now
            float xCoord = workingXCenterCoord + (workingWidth / 2);
            float yCoord = workingYCenterCoord - (workingHeight / 2);

            // do we have a rotation
            if (workingDegreesRotation != 0)
            {
                PointF pointToRotate = new PointF(xCoord, yCoord);
                // do the math and return
                return(MiscGraphicsUtils.RotatePointAboutPointByDegrees(centerPoint, workingDegreesRotation, pointToRotate));
            }
            else
            {
                // no just return the existing value
                return(new PointF(xCoord, yCoord));
            }
        }
示例#7
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Builds a graphics path from the complex object list
        /// </summary>
        /// <returns>the graphicsPath object</returns>
        public GraphicsPath GetGraphicsPathFromComplexObjectList_DCode()
        {
            GraphicsPath gPath = new GraphicsPath();

            // go through the complex object list and add the lines
            // and arcs to make a graphics path

            // first we pickup everything that bounds the region
            foreach (GerberLine_DCode dcodeObj in ComplexObjectList_DCode)
            {
                // we are only intersted in things that actually draw a line or an arc
                if (dcodeObj.DCode != 1)
                {
                    continue;
                }

                // ok at this point we know we are not bothering with the stuff that the coincident lines
                // describe. This means that we are looking at the boundary of the fill.
                if (dcodeObj.LastRadiusPlotCoord != 0)
                {
                    // non zero last radius assume we were an arc, get the enclosing rectangle
                    Rectangle outerRect = new Rectangle(dcodeObj.LastPlotCenterXCoord - dcodeObj.LastRadiusPlotCoord, dcodeObj.LastPlotCenterYCoord - dcodeObj.LastRadiusPlotCoord, 2 * dcodeObj.LastRadiusPlotCoord, 2 * dcodeObj.LastRadiusPlotCoord);
                    // add the arc, note the start angle the sweep angle must always be counterclockwise here, the start angle should already be adjusted so that +ve X axis is the zero
                    float clockwiseSweepAngle = MiscGraphicsUtils.ConvertSweepAngleToCounterClockwise(dcodeObj.LastSweepAngleWasClockwise, dcodeObj.LastSweepAngle);
                    gPath.AddArc(outerRect, dcodeObj.LastStartAngle, clockwiseSweepAngle);
                }
                else
                {
                    // assume we are a line
                    gPath.AddLine(dcodeObj.LastPlotXCoordStart, dcodeObj.LastPlotYCoordStart, dcodeObj.LastPlotXCoordEnd, dcodeObj.LastPlotYCoordEnd);
                }
            } // bottom of foreach (GerberLine_DCode dcodeObj in ComplexObjectList_DCode)

            return(gPath);
        }
示例#8
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets the yCenterCoord.
        /// </summary>
        /// <param name="varArray">the array to get the numbered variables from</param>
        public float GetYCenterCoord(GerberMacroVariableArray varArray)
        {
            if (yCenterCoord == null)
            {
                yCenterCoord = new GerberMacroVariable();
            }
            float workingYCenterCoord    = yCenterCoord.ProcessVariableStringToFloat(varArray);
            float workingDegreesRotation = GetDegreesRotation(varArray);

            // do we have a rotation
            if (workingDegreesRotation != 0)
            {
                // yes, return the converted value
                if (xCenterCoord == null)
                {
                    xCenterCoord = new GerberMacroVariable();
                }
                float  workingXCenterCoord = xCenterCoord.ProcessVariableStringToFloat(varArray);
                double angleInRadians      = MiscGraphicsUtils.DegreesToRadians(workingDegreesRotation);
                return((float)((workingYCenterCoord * Math.Cos(angleInRadians)) + workingXCenterCoord * Math.Sin(angleInRadians)));
            }
            else
            {
                // no just return the eyisting value
                return(workingYCenterCoord);
            }
        }
示例#9
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// If we fill a shape with the aperture at the current coordinates. This
        /// simulates the aperture flash of a Gerber plotter
        /// </summary>
        /// <param name="graphicsObj">a graphics object to draw on</param>
        /// <param name="workingBrush">a brush to draw with</param>
        /// <param name="x1">the x center value</param>
        /// <param name="y1">the y center value</param>
        /// <returns>z success, nz fail</returns>
        public override void FlashApertureForGerberPlot(GerberFileStateMachine stateMachine, Graphics graphicsObj, Brush workingBrush, float x1, float y1)
        {
            int xlen;
            int ylen;
            int hDia;

            if (graphicsObj == null)
            {
                return;
            }
            if (workingBrush == null)
            {
                return;
            }
            if (stateMachine == null)
            {
                return;
            }

            xlen = (int)Math.Round((this.xAxisDimension * stateMachine.IsoPlotPointsPerAppUnit));
            ylen = (int)Math.Round((this.yAxisDimension * stateMachine.IsoPlotPointsPerAppUnit));

            // do we need to draw in the hole?
            if (HoleDiameter > 0)
            {
                // yes we do, do it this way
                hDia = (int)Math.Round((this.HoleDiameter * stateMachine.IsoPlotPointsPerAppUnit));
                MiscGraphicsUtils.FillRectangleCenteredOnPoint(graphicsObj, workingBrush, x1, y1, xlen, ylen, hDia);
            }
            else
            {
                MiscGraphicsUtils.FillRectangleCenteredOnPoint(graphicsObj, workingBrush, x1, y1, xlen, ylen);
            }
            return;
        }
示例#10
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets the distance from the center to the origin
        /// </summary>
        /// <param name="varArray">the array to get the numbered variables from</param>
        public float GetCenterDistance(GerberMacroVariableArray varArray)
        {
            float xCenter = GetXCenterCoord(varArray);
            float yCenter = GetYCenterCoord(varArray);

            // get the distance
            return(MiscGraphicsUtils.GetDistanceBetweenTwoPoints(new PointF(0, 0), new PointF(xCenter, yCenter)));
        }
示例#11
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// We fill a shape with the macro primitive at the current coordinates.
        /// </summary>
        /// <param name="graphicsObj">a graphics object to draw on</param>
        /// <param name="workingBrush">a brush to draw with</param>
        /// <param name="bottomOfGraphicsObjInMacroScreenCoords_X">the macro screen coord which represents the bottom 0 coord of the graphics object</param>
        /// <param name="bottomOfGraphicsObjInMacroScreenCoords_Y">the macro screen coord which represents the bottom 0 coord of the graphics object</param>
        /// <param name="varArray">the array to get the numbered variables from</param>
        /// <returns>z success, nz fail</returns>
        public override void FlashMacroPrimitiveForGerberPlot(GerberFileStateMachine stateMachine, GerberMacroVariableArray varArray, Graphics graphicsObj, Brush workingBrush, float bottomOfGraphicsObjInMacroScreenCoords_X, float bottomOfGraphicsObjInMacroScreenCoords_Y)
        {
            if (graphicsObj == null)
            {
                return;
            }
            if (workingBrush == null)
            {
                return;
            }
            if (stateMachine == null)
            {
                return;
            }

            // note that the graphicsObj here is not the main screen. It is a smaller temporary graphics object
            // designed only to receive the macro. The underlying bitmap of this graphics object gets overlaid on the screen later

            // note the bottomOfGraphicsObjInMacroScreenCoords_? vars are not the bottom of this macro primitives space. It is the
            // screen coords of the bottom of the smallest rectangle which contains all of the macro primitives

            // get the VertexPointArray converted and rotated
            PointF[] tmpPointArray = GetPointArrayAsPointFArray(varArray);
            // collect the vertexPoints we operate on here
            PointF[] vertexPoints = new PointF[vertexPointArray.Length];

            // loop through the tmpPointArray
            for (int i = 0; i < tmpPointArray.Length; i++)
            {
                //DebugMessage("rawPoint=" + tmpPointArray[i].ToString());

                // we will need them as screen coords
                float primPointInScreenCoords_X = tmpPointArray[i].X * stateMachine.IsoPlotPointsPerAppUnit;
                float primPointInScreenCoords_Y = tmpPointArray[i].Y * stateMachine.IsoPlotPointsPerAppUnit;

                // we can calc the effective draw point of the current primitive, we do it out here to make this obvious
                float effectiveDrawPoint_X = primPointInScreenCoords_X - bottomOfGraphicsObjInMacroScreenCoords_X;
                float effectiveDrawPoint_Y = primPointInScreenCoords_Y - bottomOfGraphicsObjInMacroScreenCoords_Y;

                // create a new point and stuff it in the array
                vertexPoints[i] = new PointF(effectiveDrawPoint_X, effectiveDrawPoint_Y);
                //DebugMessage("  vertexPoint=" + vertexPoints[i].ToString());
            }


            // figure out the brush. We do not use the one passed in, we can flash in in reverse here
            Brush tmpBrush = GetDrawBrush(stateMachine, varArray);

            // Now flash
            MiscGraphicsUtils.FillOutlineCenteredOnPoint(graphicsObj, tmpBrush, vertexPoints);
        }
示例#12
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// We fill a shape with the macro primitive at the current coordinates.
        /// </summary>
        /// <param name="graphicsObj">a graphics object to draw on</param>
        /// <param name="workingBrush">a brush to draw with</param>
        /// <param name="bottomOfGraphicsObjInMacroScreenCoords_X">the macro screen coord which represents the bottom 0 coord of the graphics object</param>
        /// <param name="bottomOfGraphicsObjInMacroScreenCoords_Y">the macro screen coord which represents the bottom 0 coord of the graphics object</param>
        /// <param name="varArray">the array to get the numbered variables from</param>
        /// <returns>z success, nz fail</returns>
        public override void FlashMacroPrimitiveForGerberPlot(GerberFileStateMachine stateMachine, GerberMacroVariableArray varArray, Graphics graphicsObj, Brush workingBrush, float bottomOfGraphicsObjInMacroScreenCoords_X, float bottomOfGraphicsObjInMacroScreenCoords_Y)
        {
            if (graphicsObj == null)
            {
                return;
            }
            if (workingBrush == null)
            {
                return;
            }
            if (stateMachine == null)
            {
                return;
            }

            // note that the graphicsObj here is not the main screen. It is a smaller temporary graphics object
            // designed only to receive the macro. The underlying bitmap of this graphics object gets overlaid on the screen later

            // note the bottomOfGraphicsObjInMacroScreenCoords_? vars are not the bottom of this macro primitives space. It is the
            // screen coords of the bottom of the smallest rectangle which contains all of the macro primitives

            // get the bounding box of this primitive
            RectangleF primBoundingBox = GetMacroPrimitiveBoundingBox(varArray);
            // convert to screen values, this is still the primitive bounding rect though
            RectangleF primBoundingBoxInScreenCoords = MiscGraphicsUtils.ConvertRectFToScreenCoordinates(primBoundingBox, stateMachine);

            float workingDiameter = GetDiameter(varArray);
            int   circleDiameter  = (int)Math.Round(workingDiameter * stateMachine.IsoPlotPointsPerAppUnit);
            int   workingNumSides = (int)GetNumSides(varArray);
            float rotationAngle   = GetDegreesRotation(varArray);

            // we will need the center point coords
            float primCenterPointInScreenCoords_X = GetXCenterCoord(varArray) * stateMachine.IsoPlotPointsPerAppUnit;
            float primCenterPointInScreenCoords_Y = GetYCenterCoord(varArray) * stateMachine.IsoPlotPointsPerAppUnit;

            // we can calc the effective center point of the current primitive, we do it out here to make this obvious
            float effectiveDrawPoint_X0 = primCenterPointInScreenCoords_X - bottomOfGraphicsObjInMacroScreenCoords_X;
            float effectiveDrawPoint_Y0 = primCenterPointInScreenCoords_Y - bottomOfGraphicsObjInMacroScreenCoords_Y;

            //DebugMessage("  effectiveDrawPoint=(" + effectiveDrawPoint_X0.ToString() + "," + effectiveDrawPoint_Y0.ToString() + ")");

            // figure out the brush. We do not use the one passed in, we can flash in in reverse here
            Brush tmpBrush = GetDrawBrush(stateMachine, varArray);

            // Now flash
            MiscGraphicsUtils.FillPolygonCenteredOnPoint(graphicsObj, tmpBrush, effectiveDrawPoint_X0, effectiveDrawPoint_Y0, workingNumSides, circleDiameter, rotationAngle);
        }
示例#13
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Performs the action the plot requires based on the current context
        /// </summary>
        /// <param name="graphicsObj">a graphics object on which to plot</param>
        /// <param name="stateMachine">the excellon plot state machine</param>
        /// <param name="errorString">the error string we return on fail</param>
        /// <param name="errorValue">the error value we return on fail, z success, nz fail </param>
        /// <returns>an enum value indicating what next action to take</returns>
        public override PlotActionEnum PerformPlotExcellonAction(Graphics graphicsObj, ExcellonFileStateMachine stateMachine, ref int errorValue, ref string errorString)
        {
            int workingXCoord;
            int workingYCoord;
            int workingXOffset;
            int workingYOffset;

            if (RepeatCount < 0)
            {
                LogMessage("PerformPlotExcellonAction (R) invalid repeat count of " + RepeatCount.ToString() + " on line " + LineNumber.ToString());
                errorValue  = 101;
                errorString = "PerformPlotExcellonAction(R) invalid repeat count of " + RepeatCount.ToString() + " on line " + LineNumber.ToString();
                return(PlotActionEnum.PlotAction_FailWithError);
            }

            // setup our offsets now
            workingXOffset = GetOffsetInPlotCoords_X(stateMachine);
            workingYOffset = GetOffsetInPlotCoords_Y(stateMachine);

            // set the drill width
            float workingDrillWidth = stateMachine.LastDrillWidth * stateMachine.IsoPlotPointsPerAppUnit;

            // remember this
            LastDrillWidth = stateMachine.LastDrillWidth;

            // now put out our loop
            for (int i = 0; i < RepeatCount; i++)
            {
                workingXCoord = stateMachine.LastPlotXCoord;
                workingYCoord = stateMachine.LastPlotYCoord;

                // calculate the new coordinate now
                workingXCoord += workingXOffset;
                workingYCoord += workingYOffset;
                stateMachine.LastPlotXCoord = workingXCoord;
                stateMachine.LastPlotYCoord = workingYCoord;
                stateMachine.LastXCoord     = (float)(workingXCoord / stateMachine.IsoPlotPointsPerAppUnit);
                stateMachine.LastYCoord     = (float)(workingYCoord / stateMachine.IsoPlotPointsPerAppUnit);

                MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, stateMachine.ExcellonHoleBrush, workingXCoord, workingYCoord, workingDrillWidth, workingDrillWidth);
            }

            errorValue  = 0;
            errorString = "Successful End";
            return(PlotActionEnum.PlotAction_Continue);
        }
示例#14
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// If we draw a line with an aperture it will not always have linear ends
        /// for example if the aperture is a circle it will have half circle ends. Each
        /// line that is drawn calls this to make it look right visually
        /// </summary>
        /// <param name="graphicsObj">a graphics object to draw on</param>
        /// <param name="workingBrush">a brush to draw with</param>
        /// <param name="workingPen">the pen used for the line, we get the width from this</param>
        /// <param name="x1">the first x value</param>
        /// <param name="y1">the first y value</param>
        /// <param name="x2">the second x value</param>
        /// <param name="y2">the second y value</param>
        /// <returns>z success, nz fail</returns>
        public override void FixupLineEndpointsForGerberPlot(GerberFileStateMachine stateMachine, Graphics graphicsObj, Brush workingBrush, Pen workingPen, float x1, float y1, float x2, float y2)
        {
            if (graphicsObj == null)
            {
                return;
            }
            if (workingBrush == null)
            {
                return;
            }
            if (workingPen == null)
            {
                return;
            }

            // fix up the two end points
            MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x1, y1, workingPen.Width, workingPen.Width);
            MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x2, y2, workingPen.Width, workingPen.Width);
            return;
        }
示例#15
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Performs the action the plot requires based on the current context
        /// </summary>
        /// <param name="graphicsObj">a graphics object on which to plot</param>
        /// <param name="stateMachine">the gcode plot state machine</param>
        /// <param name="errorString">the error string we return on fail</param>
        /// <param name="errorValue">the error value we return on fail, z success, nz fail </param>
        /// <param name="wantEndPointMarkers">if true we draw the endpoints of the gcodes
        /// in a different color</param>
        /// <returns>an enum value indicating what next action to take</returns>
        public override PlotActionEnum PerformPlotGCodeAction(Graphics graphicsObj, GCodeFileStateMachine stateMachine, bool wantEndPointMarkers, ref int errorValue, ref string errorString)
        {
            Pen   workingPen   = null;
            Brush workingBrush = null;

            if (stateMachine == null)
            {
                errorValue  = 999;
                errorString = "PerformPlotGCodeAction (Line) stateMachine == null";
                return(PlotActionEnum.PlotAction_FailWithError);
            }

            if (DoNotEmitToGCode == true)
            {
                return(PlotActionEnum.PlotAction_Continue);
            }

            // GetPen, it will have been set up to have the proper width and color
            workingPen   = stateMachine.PlotBorderPen;
            workingBrush = stateMachine.PlotBorderBrush;

            //DebugTODO("remove this");
            //if (DebugID == 3) workingPen = Pens.Red;
            //if (DebugID == 1) workingPen = Pens.Green;
            //if (DebugID == 6) workingPen = Pens.Blue;
            //if (DebugID == 4) workingPen = Pens.DarkOrange;

            //if (DebugID != 3)
            //{
            //    return PlotActionEnum.PlotAction_Continue;
            //}

            // Draw the line
            graphicsObj.DrawLine(workingPen, x0, y0, x1, y1);
            // now draw in the circular end points of the line
            MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x0, y0, workingPen.Width, workingPen.Width);
            MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x1, y1, workingPen.Width, workingPen.Width);

            return(PlotActionEnum.PlotAction_Continue);
        }
示例#16
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets a vertex point from the vertexPointArray, as a converted and
        /// rotated PointF
        /// </summary>
        /// <param name="index">the index into the array</param>
        /// <param name="varArray">the array to get the numbered variables from</param>
        /// <returns>the vertex point</returns>
        private PointF GetVertexPoint(GerberMacroVariableArray varArray, int index)
        {
            // get the raw point
            PointF pointToRotate = vertexPointArray[index].ProcessVariablePairToFloat(varArray);

            // we willneed the rotation
            float workingDegreesRotation = GetDegreesRotation(varArray);

            // do we have a rotation
            if (workingDegreesRotation != 0)
            {
                // yes, return the converted value
                double angleInRadians = MiscGraphicsUtils.DegreesToRadians(workingDegreesRotation);
                float  newXVal        = (float)((pointToRotate.X * Math.Cos(angleInRadians)) - pointToRotate.Y * Math.Sin(angleInRadians));
                float  newYVal        = (float)((pointToRotate.Y * Math.Cos(angleInRadians)) + pointToRotate.X * Math.Sin(angleInRadians));
                return(new PointF(newXVal, newYVal));
            }
            else
            {
                // no just return the existing value
                return(pointToRotate);
            }
        }
示例#17
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// If we draw a line with an aperture it will not always have linear ends
        /// for example if the aperture is a circle it will have half circle ends. Each
        /// line that is drawn calls this to make it look right visually
        /// </summary>
        /// <param name="graphicsObj">a graphics object to draw on</param>
        /// <param name="workingBrush">a brush to draw with</param>
        /// <param name="workingPen">the pen used for the line, we get the width from this</param>
        /// <param name="x1">the first x value</param>
        /// <param name="y1">the first y value</param>
        /// <param name="x2">the second x value</param>
        /// <param name="y2">the second y value</param>
        /// <returns>z success, nz fail</returns>
        public override void FixupLineEndpointsForGerberPlot(GerberFileStateMachine stateMachine, Graphics graphicsObj, Brush workingBrush, Pen workingPen, float x1, float y1, float x2, float y2)
        {
            int xlen;
            int ylen;

            if (graphicsObj == null)
            {
                return;
            }
            if (workingBrush == null)
            {
                return;
            }
            if (workingPen == null)
            {
                return;
            }

            xlen = (int)Math.Round((this.xAxisDimension * stateMachine.IsoPlotPointsPerAppUnit));
            ylen = (int)Math.Round((this.yAxisDimension * stateMachine.IsoPlotPointsPerAppUnit));
            MiscGraphicsUtils.FillRectangleCenteredOnPoint(graphicsObj, workingBrush, x1, y1, xlen, ylen);
            MiscGraphicsUtils.FillRectangleCenteredOnPoint(graphicsObj, workingBrush, x2, y2, xlen, ylen);
            return;
        }
示例#18
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets two points which form a rectangle which completely encloses the arc
        /// </summary>
        public bool GetBoundingPoints(out Point lowerLeft, out Point upperRight)
        {
            Rectangle outRect = MiscGraphicsUtils.GetBoundingRectForCircle(xCenter, yCenter, Radius);

            lowerLeft  = new Point(outRect.X, outRect.Y);
            upperRight = new Point(outRect.X + outRect.Width, outRect.Y + outRect.Height);
            if (lowerLeft.X < 0)
            {
                return(false);
            }
            if (lowerLeft.Y < 0)
            {
                return(false);
            }
            if (upperRight.X < 0)
            {
                return(false);
            }
            if (upperRight.Y < 0)
            {
                return(false);
            }
            return(true);
        }
示例#19
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Performs the action the plot requires based on the current context
        /// </summary>
        /// <param name="graphicsObj">a graphics object on which to plot</param>
        /// <param name="stateMachine">the gerber plot state machine</param>
        /// <param name="errorString">the error string we return on fail</param>
        /// <param name="errorValue">the error value we return on fail, z success, nz fail </param>
        /// <returns>an enum value indicating what next action to take</returns>
        public override GerberLine.PlotActionEnum PerformPlotGerberAction(Graphics graphicsObj, GerberFileStateMachine stateMachine, ref int errorValue, ref string errorString)
        {
            // one would think that turning off the contouring would be all that was necessary. However
            // contours are complex object and sometime we have to finish off the object usually this
            // means fill the existing contour object .
            if ((stateMachine.ContourDrawingModeEnabled == true) && (stateMachine.ComplexObjectList_DCode.Count != 0))
            {
                // we have an existing complex object, we process it there

                // Create solid brush.
                SolidBrush fillBrush = (SolidBrush)stateMachine.GerberContourFillBrush;
                // Get the bounding box
                Rectangle boundingRect = stateMachine.GetBoundingRectangleFromComplexObjectList_DCode();
                // get a graphics path defining this object
                GraphicsPath gPath = stateMachine.GetGraphicsPathFromComplexObjectList_DCode();
                MiscGraphicsUtils.FillRectangleUsingGraphicsPath(graphicsObj, gPath, boundingRect, fillBrush);
                // reset the complex object list
                stateMachine.ComplexObjectList_DCode = new List <GerberLine_DCode>();
            }

            // enable contour drawing mode
            stateMachine.ContourDrawingModeEnabled = false;
            return(GerberLine.PlotActionEnum.PlotAction_Continue);
        }
示例#20
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Flashes the rectangular aperture at a point
        /// </summary>
        /// <param name="isoPlotBuilder">the builder opbject</param>
        /// <param name="stateMachine">the statemachine</param>
        /// <param name="xyComp">the xy compensation factor</param>
        /// <param name="x1">the first x value</param>
        /// <param name="y1">the first y value</param>
        /// <returns>z success, nz fail</returns>
        public override void FlashApertureForGCodePlot(IsoPlotBuilder isoPlotBuilder, GerberFileStateMachine stateMachine, int x1, int y1, int xyComp)
        {
            int holeBuilderObjID = 0;
            int hDia;

            if (isoPlotBuilder == null)
            {
                return;
            }
            if (stateMachine == null)
            {
                return;
            }

            int xComp = (int)Math.Round(((XAxisDimension * stateMachine.IsoPlotPointsPerAppUnit)));
            int yComp = (int)Math.Round(((YAxisDimension * stateMachine.IsoPlotPointsPerAppUnit) / 2));

            if (stateMachine.BackgroundFillModeAccordingToPolarity == GSFillModeEnum.FillMode_BACKGROUND)
            {
                // corrected, courtesy of MaikF
                int builderID = isoPlotBuilder.DrawGSLineOutLine(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_NORMALEDGE, x1, y1 - yComp - xyComp / 2, x1, y1 + yComp + xyComp / 2, xComp + (1 * xyComp), stateMachine.BackgroundFillModeAccordingToPolarity);
                // do we need to do a hole?
                if (HoleDiameter > 0)
                {
                    // yes we do
                    hDia = (int)Math.Round((HoleDiameter * stateMachine.IsoPlotPointsPerAppUnit));
                    int holeRadius = (hDia - xyComp) / 2;
                    if (holeRadius > 0)
                    {
                        // draw the circle for the hole
                        holeBuilderObjID = isoPlotBuilder.DrawGSCircle(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_NORMALEDGE, x1, y1, holeRadius, GSFillModeEnum.FillMode_BACKGROUND, stateMachine.WantClockWise);

                        // There is more going on here than is immediately obvious
                        // we want the inside of the hole to not be filled with isocells from the holeBuilderObjID
                        // we could just have not filled it and only placed edge isocells
                        // but this causes complications on the erase. It is better to fill it then remove the outer
                        // object then remove the background only pixels of the holeBuilderObjID. This makes sure we
                        // get all of the outer objects isocells rather than relying on hitting the edge to
                        // figure out where to start.

                        // remove everything belonging to the outer circle from the circle we just drew, this
                        // leaves anything else which might be in there in there
                        isoPlotBuilder.EraseABuilderIDFromRegionUsingABuilderID(holeBuilderObjID, builderID, x1 - holeRadius - 1, y1 - holeRadius - 1, x1 + holeRadius + 1, y1 + holeRadius + 1);

                        // remove all background only pixels belonging to the hole circle leaving just the edge pixels
                        isoPlotBuilder.EraseBackgroundOnlyIsoCellsByBuilderID(holeBuilderObjID, x1 - holeRadius - 1, y1 - holeRadius - 1, x1 + holeRadius + 1, y1 + holeRadius + 1);
                    }
                }
            } // bottom of if (stateMachine.BackgroundFillModeAccordingToPolarity == GSFillModeEnum.FillMode_BACKGROUND)
            else if (stateMachine.BackgroundFillModeAccordingToPolarity == GSFillModeEnum.FillMode_ERASE)
            {
                // we have to decide whether we are drawing a hole or not. In Clear Polarity holes do not come in as solid DARK spot like you
                // think they would. Instead they just "do nothing" on the area the contents below them remain there and there is no fill or erase

                if (HoleDiameter > 0)
                {
                    // we are dealing with a erase flash with a transparent hole

                    // draw the rectangle, we use invert edges here so we draw the circle only if it is on some other background, use no fill. We will erase between it and the hole later
                    int builderID = isoPlotBuilder.DrawGSLineOutLine(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_INVERTEDGE, x1, y1 - yComp - xyComp / 2, x1, y1 + yComp + xyComp / 2, xComp + (1 * xyComp), GSFillModeEnum.FillMode_NONE);

                    // now do the hole we use invert edges so anything we draw over a background will get drawn, there is no fill
                    hDia = (int)Math.Round((HoleDiameter * stateMachine.IsoPlotPointsPerAppUnit));
                    int holeRadius = (hDia - xyComp) / 2;
                    if (holeRadius > 0)
                    {
                        // draw the circle for the hole using no fill. Whatever is in there is in there
                        holeBuilderObjID = isoPlotBuilder.DrawGSCircle(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_INVERTEDGE, x1, y1, holeRadius, GSFillModeEnum.FillMode_NONE, stateMachine.WantClockWise);
                    }
                    // now erase between the outer and inner circles
                    // we are dealing with a simple erase flash, no hole
                    List <int> builderIDList = new List <int>();
                    builderIDList.Add(builderID);
                    builderIDList.Add(holeBuilderObjID);
                    MiscGraphicsUtils.GetWideLineEndPoints(x1, y1 - yComp - xyComp / 2, x1, y1 + yComp + xyComp / 2, xComp + (1 * xyComp), out Point ptLL, out Point ptUL, out Point ptUR, out Point ptLR);
                    // now erase the background
                    isoPlotBuilder.BackgroundFillGSByBoundaryComplexVert(builderIDList, IsoPlotObject.DEFAULT_ISOPLOTOBJECT_ID, ptLL.X, ptLL.Y, ptUR.X, ptUR.Y, -1);
                }
                else
                {
                    // draw the rectangle, we use invert edges here so we draw only if it is on some other background, we still erase everything under it though
                    int builderID = isoPlotBuilder.DrawGSLineOutLine(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_INVERTEDGE, x1, y1 - yComp - xyComp / 2, x1, y1 + yComp + xyComp / 2, xComp + (1 * xyComp), GSFillModeEnum.FillMode_ERASE);
                }
            }
        }
示例#21
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Performs the action the plot requires based on the current context. Note
        /// that the coordinates stored in GCodeCmds in here are not in isoPlot coords.
        /// They coords are are in
        /// </summary>
        /// <param name="graphicsObj">a graphics object on which to plot</param>
        /// <param name="stateMachine">the gcode plot state machine</param>
        /// <param name="errorString">the error string we return on fail</param>
        /// <param name="errorValue">the error value we return on fail, z success, nz fail </param>
        /// <param name="wantEndPointMarkers">if true we draw the endpoints of the gcodes
        /// in a different color</param>
        /// <returns>an enum value indicating what next action to take</returns>
        public override PlotActionEnum PerformPlotGCodeAction(Graphics graphicsObj, GCodeFileStateMachine stateMachine, bool wantEndPointMarkers, ref int errorValue, ref string errorString)
        {
            Pen   workingPen   = null;
            Brush workingBrush = null;

            if (DoNotEmitToGCode == true)
            {
                return(PlotActionEnum.PlotAction_Continue);
            }

            // get the current X,Y coordinates, these will already be scaled, origin compensated and flipped
            float startXCoord = x0;
            float startYCoord = y0;

            // get the end X,Y coordinate
            float endXCoord = x1;
            float endYCoord = y1;

            // get the arc center point, by adding on the specified offsets. Note we do not involve
            // the end coords here. These are calculated off the start coords
            float arcCenterXCoord = xCenter;
            float arcCenterYCoord = yCenter;

            // get our points
            PointF startPoint  = new PointF(startXCoord, startYCoord);
            PointF endPoint    = new PointF(endXCoord, endYCoord);
            PointF centerPoint = new PointF(arcCenterXCoord, arcCenterYCoord);

            //DebugMessage("PG startPoint=" + startPoint.ToString() + ", endPoint=" + endPoint.ToString() + ", centerPoint=" + centerPoint.ToString() + ", radius=" + radius);

            // A NOTE on the direction of angles here. Gerber can specifiy clockwise or counter clockwise. .NET only wants its angles specified counter
            // clockwise when it draws. GCode can go either way. However, the arcs drawn here are segments of a larger arc (or cicle) and these are
            // built out of isoplot segments. The isoplot segment collector always goes around arcs in a counter clockwise direction. This essentially
            // converts any clockwise arcs into counter clockwise ones.

            // this means that all start points, end points and sweep angles are ALWAYS listed as CounterClockwise here even if the original gerber was
            // clockwise. This means we do not have to do any conversion for the display even if the original angle was clockwise.

            // get our start and sweep angles
            MiscGraphicsUtils.GetCounterClockwiseStartAndSweepAnglesFrom2PointsAndCenter(startPoint, endPoint, centerPoint, out float startAngleInDegrees, out float sweepAngleInDegrees);

            //DebugMessage("  PGa startAngleInDegrees=" + startAngleInDegrees.ToString() + ", sweepAngleInDegrees=" + sweepAngleInDegrees.ToString());

            // are we dealing with a sweep angle of 0 degrees?
            if (sweepAngleInDegrees == 0)
            {
                // yes, this actually may be a full circle or it may just be a tiny little arc segment with an angle so small
                // that it cannot be drawn. We can get an idea by looking at the number of isoPlotCells the arc uses. A small
                // number indicates that we are actually a circle
                if (IsoPlotCellsInObject >= ARBITRARY_MIN_NUMBER_OF_CELLS_FOR_0_DEGREE_ARC)
                {
                    sweepAngleInDegrees = 360;
                }
            }

            // GetPen, it will have been set up to have the proper width and color
            workingPen   = stateMachine.PlotBorderPen;
            workingBrush = stateMachine.PlotBorderBrush;

            // create an enclosing rectangle
            RectangleF boundingRect = new RectangleF(arcCenterXCoord - radius, arcCenterYCoord - radius, 2 * radius, 2 * radius);

            //DebugTODO("remove this");
            //if (DebugID == 23) workingPen = Pens.Red;
            //if (DebugID == 25) workingPen = Pens.Green;
            //if (DebugID == 20) workingPen = Pens.Blue;
            //if (DebugID != 9)
            //{
            //    return PlotActionEnum.PlotAction_Continue;
            //}

            // Draw arc
            graphicsObj.DrawArc(workingPen, boundingRect, startAngleInDegrees, sweepAngleInDegrees);

            // if we did not do nothing or a full circle draw these in
            if (((sweepAngleInDegrees == 0) || (sweepAngleInDegrees == 360)) == false)
            {
                // now draw in the circular end points of the line
                MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, startXCoord, startYCoord, workingPen.Width, workingPen.Width);
                MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, endXCoord, endYCoord, workingPen.Width, workingPen.Width);
            }

            return(PlotActionEnum.PlotAction_Continue);
        }
示例#22
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// If we fill a shape with the aperture at the current coordinates. This
        /// simulates the aperture flash of a Gerber plotter
        /// </summary>
        /// <param name="graphicsObj">a graphics object to draw on</param>
        /// <param name="workingBrush">a brush to draw with</param>
        /// <param name="x1">the x center value</param>
        /// <param name="y1">the y center value</param>
        /// <returns>z success, nz fail</returns>
        public override void FlashApertureForGerberPlot(GerberFileStateMachine stateMachine, Graphics graphicsObj, Brush workingBrush, float x1, float y1)
        {
            bool  ellipseIsVertical    = false;
            int   workingOuterDiameter = int.MinValue;
            float majorOBRoundAxis     = float.NegativeInfinity;
            float minorOBRoundAxis     = float.NegativeInfinity;
            float majorOBRoundAxisAdjustedForCircle = float.NegativeInfinity;
            float x1_OBRoundCompensatedEndpoint;
            float y1_OBRoundCompensatedEndpoint;
            float x2_OBRoundCompensatedEndpoint;
            float y2_OBRoundCompensatedEndpoint;
            float majorOBRoundAxisEndpointCompensation = 0;
            float minorOBRoundAxisEndpointCompensation = 0;
            int   hDia;

            if (graphicsObj == null)
            {
                return;
            }
            if (workingBrush == null)
            {
                return;
            }
            if (stateMachine == null)
            {
                return;
            }

            // NOTE: it is not possible to encode an Oval or ellipse in Gerber, you have to
            //       represent this with a line segment which has two circles at the end
            //       the total length should be equal the longest dimension. The shortest
            //       dimension will be used as the diameter of the circles.

            // NOTE: we need not deal with ellipses in here which do not have major and minor
            //       axis parallel to the X and Y axis. There is no way to represent this in
            //       Gerber code and they are usually encoded as an AM macro which is a
            //       combination of two circles and a line - just as we are doing (see above)
            //       and for exactly the same reasons.

            // find the shortest and longest dimensions
            if (xAxisDimension > yAxisDimension)
            {
                majorOBRoundAxis  = xAxisDimension;
                minorOBRoundAxis  = yAxisDimension;
                ellipseIsVertical = false;
            }
            else
            {
                majorOBRoundAxis  = yAxisDimension;
                minorOBRoundAxis  = xAxisDimension;
                ellipseIsVertical = true;
            }
            // now figure out the length of the line between the circles
            majorOBRoundAxisAdjustedForCircle = majorOBRoundAxis - minorOBRoundAxis;
            // sanity checks
            if (majorOBRoundAxisAdjustedForCircle < 0)
            {
                // what the hell? we got problems
                throw new Exception("Cannot draw OBRound adjusted axis less than zero.");
            }
            else if (majorOBRoundAxisAdjustedForCircle == 0)
            {
                // we must be dealing with a circle, just draw one
                workingOuterDiameter = (int)Math.Round((minorOBRoundAxis * stateMachine.IsoPlotPointsPerAppUnit));
                // do we have an internal hole?
                if (HoleDiameter > 0)
                {
                    // yes we do
                    hDia = (int)Math.Round((this.HoleDiameter * stateMachine.IsoPlotPointsPerAppUnit));
                    MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x1, y1, workingOuterDiameter, workingOuterDiameter, hDia);
                }
                else
                {
                    MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x1, y1, workingOuterDiameter, workingOuterDiameter);
                }
                return;
            }
            // now figure out the diameter of the endpoint circles
            workingOuterDiameter = (int)Math.Round((minorOBRoundAxis * stateMachine.IsoPlotPointsPerAppUnit));

            // calc the amount we have to add/subtract on the center point to get to the endpoints
            majorOBRoundAxisEndpointCompensation = (int)Math.Round(((majorOBRoundAxisAdjustedForCircle * stateMachine.IsoPlotPointsPerAppUnit) / 2));
            minorOBRoundAxisEndpointCompensation = (int)Math.Round(((minorOBRoundAxis * stateMachine.IsoPlotPointsPerAppUnit) / 2));

            // get the lengths of the rectangle joining the circles
            int majorOBRoundAxisLen = (int)Math.Round(majorOBRoundAxisAdjustedForCircle * stateMachine.IsoPlotPointsPerAppUnit);
            int minorOBRoundAxisLen = (int)Math.Round(minorOBRoundAxis * stateMachine.IsoPlotPointsPerAppUnit);

            // compensate the endpoints, the way we do this is dependent on whether
            // the ellipse is horizontal or vertical
            if (ellipseIsVertical == false)
            {
                x1_OBRoundCompensatedEndpoint = x1 - majorOBRoundAxisEndpointCompensation;
                x2_OBRoundCompensatedEndpoint = x1 + majorOBRoundAxisEndpointCompensation;
                y1_OBRoundCompensatedEndpoint = y1;
                y2_OBRoundCompensatedEndpoint = y1;
            }
            else
            {
                x1_OBRoundCompensatedEndpoint = x1;
                x2_OBRoundCompensatedEndpoint = x1;
                y1_OBRoundCompensatedEndpoint = y1 - majorOBRoundAxisEndpointCompensation;
                y2_OBRoundCompensatedEndpoint = y1 + majorOBRoundAxisEndpointCompensation;
            }

            // do we need to draw in the hole?
            if (HoleDiameter > 0)
            {
                // yes we do
                hDia = (int)Math.Round((this.HoleDiameter * stateMachine.IsoPlotPointsPerAppUnit));
                // draw the first circle endpoint
                MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x1_OBRoundCompensatedEndpoint, y1_OBRoundCompensatedEndpoint, workingOuterDiameter, workingOuterDiameter, hDia, x1, y1);
                // draw the second circle endpoint
                MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x2_OBRoundCompensatedEndpoint, y2_OBRoundCompensatedEndpoint, workingOuterDiameter, workingOuterDiameter, hDia, x1, y1);
                // draw the connecting rectangle between the circle centers, we already know the centerpoint (x1, y1)
                if (ellipseIsVertical == false)
                {
                    MiscGraphicsUtils.FillRectangleCenteredOnPoint(graphicsObj, workingBrush, x1, y1, minorOBRoundAxisLen, majorOBRoundAxisLen, hDia);
                }
                else
                {
                    MiscGraphicsUtils.FillRectangleCenteredOnPoint(graphicsObj, workingBrush, x1, y1, majorOBRoundAxisLen, minorOBRoundAxisLen, hDia);
                }
            }
            else
            {
                // draw the first circle endpoint
                MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x1_OBRoundCompensatedEndpoint, y1_OBRoundCompensatedEndpoint, workingOuterDiameter, workingOuterDiameter);
                // draw the second circle endpoint
                MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x2_OBRoundCompensatedEndpoint, y2_OBRoundCompensatedEndpoint, workingOuterDiameter, workingOuterDiameter);
                if (ellipseIsVertical == false)
                {
                    MiscGraphicsUtils.FillRectangleCenteredOnPoint(graphicsObj, workingBrush, x1, y1, majorOBRoundAxisLen, workingOuterDiameter);
                }
                else
                {
                    MiscGraphicsUtils.FillRectangleCenteredOnPoint(graphicsObj, workingBrush, x1, y1, workingOuterDiameter, majorOBRoundAxisLen);
                }
            }
            return;
        }
示例#23
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Flash an aperture for a OBRound on a GCode Plot
        ///
        /// </summary>
        /// <param name="isoPlotBuilder">the builder opbject</param>
        /// <param name="stateMachine">the statemachine</param>
        /// <param name="xyComp">the xy compensation factor</param>
        /// <param name="x1">the first x value</param>
        /// <param name="y1">the first y value</param>
        /// <returns>z success, nz fail</returns>
        public override void FlashApertureForGCodePlot(IsoPlotBuilder isoPlotBuilder, GerberFileStateMachine stateMachine, int x1, int y1, int xyComp)
        {
            int   holeBuilderObjID = 0;
            int   hDia;
            bool  ellipseIsVertical    = false;
            int   workingOuterDiameter = int.MinValue;
            float majorEllipseAxis     = float.NegativeInfinity;
            float minorEllipseAxis     = float.NegativeInfinity;
            float majorEllipseAxisAdjustedForCircle = float.NegativeInfinity;
            int   x1EllipseCompensatedCenterpoint;
            int   y1EllipseCompensatedCenterpoint;
            int   x2EllipseCompensatedCenterpoint;
            int   y2EllipseCompensatedCenterpoint;
            float circle1StartDegrees = 90;
            float circle2StartDegrees = 270;
            float circle1SweepDegrees = 180;
            float circle2SweepDegrees = 180;
            int   majorEllipseAxisEndpointCompensation = 0;

            int outerBoundingBoxLL_X = 0;
            int outerBoundingBoxLL_Y = 0;
            int outerBoundingBoxUR_X = 0;
            int outerBoundingBoxUR_Y = 0;

            if (isoPlotBuilder == null)
            {
                return;
            }
            if (stateMachine == null)
            {
                return;
            }

            // NOTE: it is not possible to encode an Oval or Ellipse in GCode, you have to
            //       represent this with a line segment which has two circles at the end
            //       the total length should be equal the longest dimension. The shortest
            //       dimension will be used as the diameter of the circles.

            // NOTE: we need not deal with ellipses in here which do not have major and minor
            //       axis parallel to the X and Y axis. There is no way to represent this in
            //       Gerber code and they are usually encoded as an AM macro which is a
            //       combination of two circles and a line - just as we are doing (see above)
            //       and for exactly the same reasons.

            // find the shortest and longest dimensions. NOTE according to the spec OBRounds
            // cannot have a rotation. They are either Horizontal or Vertical
            if (xAxisDimension > yAxisDimension)
            {
                majorEllipseAxis  = xAxisDimension;
                minorEllipseAxis  = yAxisDimension;
                ellipseIsVertical = false;
            }
            else
            {
                majorEllipseAxis  = yAxisDimension;
                minorEllipseAxis  = xAxisDimension;
                ellipseIsVertical = true;
            }
            // now figure out the length of the line between the circles
            majorEllipseAxisAdjustedForCircle = majorEllipseAxis - minorEllipseAxis;
            // sanity checks
            if (majorEllipseAxisAdjustedForCircle < 0)
            {
                // what the hell? we got problems
                throw new Exception("Cannot draw ellipse adjusted axis less than zero.");
            }
            else if (majorEllipseAxisAdjustedForCircle == 0)
            {
                // special case, we must be dealing with a circle, just draw one
                workingOuterDiameter = (int)Math.Round((majorEllipseAxis * stateMachine.IsoPlotPointsPerAppUnit));
                // now do the flash
                GerberAperture_CCode.PerformCircularApertureFlashWithHole(isoPlotBuilder, stateMachine, x1, y1, xyComp, workingOuterDiameter, HoleDiameter);
                return;
            }

            // we are not dealing with a circle. We are dealing with an OBRound

            // now figure out the diameter of the endpoint circles
            workingOuterDiameter = (int)Math.Round((minorEllipseAxis * stateMachine.IsoPlotPointsPerAppUnit));
            // calc the amount we have to add/subtract on the center point to get to the
            // endpoints
            majorEllipseAxisEndpointCompensation  = (int)Math.Round(((majorEllipseAxisAdjustedForCircle * stateMachine.IsoPlotPointsPerAppUnit) / 2));
            majorEllipseAxisEndpointCompensation += (xyComp / 2);

            // compensate the endpoints, the way we do this is dependent on whether
            // the ellipse is horizontal or vertical. NOTE according to the spec OBRounds
            // cannot have a rotation. They are either Horizontal or Vertical
            if (ellipseIsVertical == false)
            {
                x1EllipseCompensatedCenterpoint = x1 - majorEllipseAxisEndpointCompensation;
                x2EllipseCompensatedCenterpoint = x1 + majorEllipseAxisEndpointCompensation;
                y1EllipseCompensatedCenterpoint = y1;
                y2EllipseCompensatedCenterpoint = y1;
                circle1StartDegrees             = 90;
                circle1SweepDegrees             = 180;
                circle2StartDegrees             = 270;
                circle2SweepDegrees             = 180;
            }
            else
            {
                x1EllipseCompensatedCenterpoint = x1;
                x2EllipseCompensatedCenterpoint = x1;
                y1EllipseCompensatedCenterpoint = y1 - majorEllipseAxisEndpointCompensation;
                y2EllipseCompensatedCenterpoint = y1 + majorEllipseAxisEndpointCompensation;
                circle1StartDegrees             = 180;
                circle1SweepDegrees             = 180;
                circle2StartDegrees             = 0;
                circle2SweepDegrees             = 180;
            }

            // calculate the endpoints of the wide line rectangle.
            MiscGraphicsUtils.GetWideLineEndPoints(x1EllipseCompensatedCenterpoint, y1EllipseCompensatedCenterpoint, x2EllipseCompensatedCenterpoint, y2EllipseCompensatedCenterpoint, (workingOuterDiameter + xyComp), out Point ptLL, out Point ptUL, out Point ptUR, out Point ptLR);
            // now set the dimensions of the bounding box
            if (ellipseIsVertical == false)
            {
                outerBoundingBoxLL_X = ptLL.X - x1EllipseCompensatedCenterpoint;
                outerBoundingBoxLL_Y = ptLL.Y;
                outerBoundingBoxUR_X = ptUR.X + x2EllipseCompensatedCenterpoint;
                outerBoundingBoxUR_Y = ptUR.Y;
            }
            else
            {
                outerBoundingBoxLL_X = ptLL.X;
                outerBoundingBoxLL_Y = ptLL.Y - y1EllipseCompensatedCenterpoint;
                outerBoundingBoxUR_X = ptUR.X;
                outerBoundingBoxUR_Y = ptUR.Y + y2EllipseCompensatedCenterpoint;
            }

            // now we draw according to the polarity

            if (stateMachine.BackgroundFillModeAccordingToPolarity == GSFillModeEnum.FillMode_BACKGROUND)
            {
                // draw the first arc
                int circle1BuilderID = isoPlotBuilder.DrawGSContourArc(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_NORMALEDGE, x1EllipseCompensatedCenterpoint, y1EllipseCompensatedCenterpoint, circle1StartDegrees, circle1SweepDegrees, ((workingOuterDiameter + xyComp) / 2), false, true, false);
                // draw the second arc
                int circle2BuilderID = isoPlotBuilder.DrawGSContourArc(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_NORMALEDGE, x2EllipseCompensatedCenterpoint, y2EllipseCompensatedCenterpoint, circle2StartDegrees, circle2SweepDegrees, ((workingOuterDiameter + xyComp) / 2), false, true, false);
                // draw in the top line
                int line1BuilderID = isoPlotBuilder.DrawGSLineContourLine(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_NORMALEDGE, ptUL.X, ptUL.Y, ptUR.X, ptUR.Y);
                // draw in the bottom line
                int line2BuilderID = isoPlotBuilder.DrawGSLineContourLine(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_NORMALEDGE, ptLL.X, ptLL.Y, ptLR.X, ptLR.Y);

                // create a list of the builder IDs used
                List <int> builderIDList = new List <int>();
                builderIDList.Add(circle1BuilderID);
                builderIDList.Add(circle2BuilderID);
                builderIDList.Add(line1BuilderID);
                builderIDList.Add(line2BuilderID);

                // now background fill the complex object, note how we only fill with the circle1BuilderID, This will be important when filling in the hole
                isoPlotBuilder.BackgroundFillGSByBoundaryComplexVert(builderIDList, circle1BuilderID, outerBoundingBoxLL_X, outerBoundingBoxLL_Y, outerBoundingBoxUR_X, outerBoundingBoxUR_Y, -1);

                // do we need to do a hole?
                if (HoleDiameter > 0)
                {
                    // yes we do
                    hDia = (int)Math.Round((HoleDiameter * stateMachine.IsoPlotPointsPerAppUnit));
                    int holeRadius = (hDia - xyComp) / 2;
                    if (holeRadius > 0)
                    {
                        // draw the circle for the hole
                        holeBuilderObjID = isoPlotBuilder.DrawGSCircle(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_NORMALEDGE, x1, y1, holeRadius, GSFillModeEnum.FillMode_BACKGROUND, stateMachine.WantClockWise);

                        // There is more going on here than is immediately obvious
                        // we want the inside of the hole to not be filled with isocells from the holeBuilderObjID
                        // we could just have not filled it and only placed edge isocells
                        // but this causes complications on the erase. It is better to fill it then remove the outer
                        // object then remove the background only pixels of the holeBuilderObjID. This makes sure we
                        // get all of the outer objects isocells rather than relying on hitting the edge to
                        // figure out where to start.

                        // remove everything belonging to the obRoundObj we just drew, note we only filled with circle1BuilderID above so that is all we need to remove
                        isoPlotBuilder.EraseABuilderIDFromRegionUsingABuilderID(holeBuilderObjID, circle1BuilderID, x1 - holeRadius - 1, y1 - holeRadius - 1, x1 + holeRadius + 1, y1 + holeRadius + 1);

                        // remove all background only pixels belonging to the hole circle leaving just the edge pixels
                        isoPlotBuilder.EraseBackgroundOnlyIsoCellsByBuilderID(holeBuilderObjID, x1 - holeRadius - 1, y1 - holeRadius - 1, x1 + holeRadius + 1, y1 + holeRadius + 1);
                    }
                }
            } // bottom of if (stateMachine.BackgroundFillModeAccordingToPolarity == GSFillModeEnum.FillMode_BACKGROUND)
            else if (stateMachine.BackgroundFillModeAccordingToPolarity == GSFillModeEnum.FillMode_ERASE)
            {
                // we have to decide whether we are drawing a hole or not. In Clear Polarity holes do not come in as solid DARK spot like you
                // think they would. Instead they just "do nothing" on the area the contents below them remain there and there is no fill or erase

                if (HoleDiameter > 0)
                {
                    // we are dealing with a erase flash with a transparent hole

                    // draw the first arc
                    int circle1BuilderID = isoPlotBuilder.DrawGSContourArc(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_INVERTEDGE, x1EllipseCompensatedCenterpoint, y1EllipseCompensatedCenterpoint, circle1StartDegrees, circle1SweepDegrees, ((workingOuterDiameter + xyComp) / 2), false, true, false);
                    // draw the second arc
                    int circle2BuilderID = isoPlotBuilder.DrawGSContourArc(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_INVERTEDGE, x2EllipseCompensatedCenterpoint, y2EllipseCompensatedCenterpoint, circle2StartDegrees, circle2SweepDegrees, ((workingOuterDiameter + xyComp) / 2), false, true, false);
                    // draw in the top line
                    int line1BuilderID = isoPlotBuilder.DrawGSLineContourLine(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_INVERTEDGE, ptUL.X, ptUL.Y, ptUR.X, ptUR.Y);
                    // draw in the bottom line
                    int line2BuilderID = isoPlotBuilder.DrawGSLineContourLine(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_INVERTEDGE, ptLL.X, ptLL.Y, ptLR.X, ptLR.Y);

                    // create a list of the builder IDs used
                    List <int> builderIDList = new List <int>();
                    builderIDList.Add(circle1BuilderID);
                    builderIDList.Add(circle2BuilderID);
                    builderIDList.Add(line1BuilderID);
                    builderIDList.Add(line2BuilderID);

                    // note that at this point we effectively have an invert edge OBRound with FillMode_NONE

                    // now do the hole we use invert edges so anything we draw over a background will get drawn, there is no fill
                    hDia = (int)Math.Round((HoleDiameter * stateMachine.IsoPlotPointsPerAppUnit));
                    int holeRadius = (hDia - xyComp) / 2;
                    if (holeRadius > 0)
                    {
                        // draw the circle for the hole using no fill. Whatever is in there is in there
                        holeBuilderObjID = isoPlotBuilder.DrawGSCircle(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_INVERTEDGE, x1, y1, holeRadius, GSFillModeEnum.FillMode_NONE, stateMachine.WantClockWise);
                    }
                    builderIDList.Add(holeBuilderObjID);

                    // now erase between the outer and inner circles
                    isoPlotBuilder.BackgroundFillGSByBoundaryComplexVert(builderIDList, IsoPlotObject.DEFAULT_ISOPLOTOBJECT_ID, outerBoundingBoxLL_X, outerBoundingBoxLL_Y, outerBoundingBoxUR_X, outerBoundingBoxUR_Y, -1);
                }
                else
                {
                    // draw the obRound, we use invert edges here so we draw only if it is on some other background, we still erase everything under it though
                    // draw the first arc
                    int circle1BuilderID = isoPlotBuilder.DrawGSContourArc(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_INVERTEDGE, x1EllipseCompensatedCenterpoint, y1EllipseCompensatedCenterpoint, circle1StartDegrees, circle1SweepDegrees, ((workingOuterDiameter + xyComp) / 2), false, true, false);
                    // draw the second arc
                    int circle2BuilderID = isoPlotBuilder.DrawGSContourArc(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_INVERTEDGE, x2EllipseCompensatedCenterpoint, y2EllipseCompensatedCenterpoint, circle2StartDegrees, circle2SweepDegrees, ((workingOuterDiameter + xyComp) / 2), false, true, false);
                    // draw in the top line
                    int line1BuilderID = isoPlotBuilder.DrawGSLineContourLine(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_INVERTEDGE, ptUL.X, ptUL.Y, ptUR.X, ptUR.Y);
                    // draw in the bottom line
                    int line2BuilderID = isoPlotBuilder.DrawGSLineContourLine(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_INVERTEDGE, ptLL.X, ptLL.Y, ptLR.X, ptLR.Y);

                    // create a list of the builder IDs used
                    List <int> builderIDList = new List <int>();
                    builderIDList.Add(circle1BuilderID);
                    builderIDList.Add(circle2BuilderID);
                    builderIDList.Add(line1BuilderID);
                    builderIDList.Add(line2BuilderID);

                    // now erase the background
                    isoPlotBuilder.BackgroundFillGSByBoundaryComplexVert(builderIDList, IsoPlotObject.DEFAULT_ISOPLOTOBJECT_ID, outerBoundingBoxLL_X, outerBoundingBoxLL_Y, outerBoundingBoxUR_X, outerBoundingBoxUR_Y, -1);
                }
            }


            /*
             *                  DebugMessage("");
             *                  DebugMessage("majorEllipseAxis=" + (majorEllipseAxis * stateMachine.IsoPlotPointsPerAppUnit));
             *                  DebugMessage("minorEllipseAxis =" + (minorEllipseAxis * stateMachine.IsoPlotPointsPerAppUnit).ToString());
             *                  DebugMessage("y1EllipseCompensatedCenterpoint =" + (y1EllipseCompensatedCenterpoint).ToString());
             *                  DebugMessage("y2EllipseCompensatedCenterpoint =" + (y2EllipseCompensatedCenterpoint).ToString());
             *                  DebugMessage("y2EllipseCompensatedCenterpoint-y1EllipseCompensatedCenterpoint =" + (y2EllipseCompensatedCenterpoint - y1EllipseCompensatedCenterpoint).ToString());
             *                  DebugMessage("xyComp =" + xyComp.ToString());
             *                  DebugMessage("workingOuterDiameter =" + workingOuterDiameter.ToString());
             *                  DebugMessage("");
             */
            return;
        }
示例#24
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Flash a macro primitive for a CLine on a GCode Plot
        /// </summary>
        /// <param name="isoPlotBuilder">the builder opbject</param>
        /// <param name="stateMachine">the statemachine</param>
        /// <param name="macroBuilderIDs">a list of builder IDs which have drawn in POSITIVE on this macro</param>
        /// <param name="xyComp">the xy compensation factor</param>
        /// <param name="x1">the first x value</param>
        /// <param name="y1">the first y value</param>
        /// <param name="varArray">the array to get the numbered variables from</param>
        /// <returns>z success, nz fail</returns>
        public override int FlashMacroPrimitiveForGCodePlot(GerberMacroVariableArray varArray, List <int> macroBuilderIDs, IsoPlotBuilder isoPlotBuilder, GerberFileStateMachine stateMachine, int x1, int y1, int xyComp)
        {
            // now do the flash
            int builderID = 0;

            if (isoPlotBuilder == null)
            {
                return(-1);
            }
            if (stateMachine == null)
            {
                return(-1);
            }
            if (macroBuilderIDs == null)
            {
                return(-1);
            }

            // figure out width and height
            float workingWidth             = GetWidth(varArray);
            int   lineWidthInScreenCoords  = (int)Math.Round(workingWidth * stateMachine.IsoPlotPointsPerAppUnit);
            float workingHeight            = GetLineLength(varArray);
            int   lineHeightInScreenCoords = (int)Math.Round(workingHeight * stateMachine.IsoPlotPointsPerAppUnit);

            //DebugMessage("efc_X=" + effectiveCenter_X.ToString() + ", " + "efc_Y=" + effectiveCenter_Y.ToString());

            // figure out the xyComp in plot coords, it comes in as screen coords here
            // we need it to feed into the rotation calculations
            float xyCompInPlotCoords = ((float)xyComp) / stateMachine.IsoPlotPointsPerAppUnit;

            xyCompInPlotCoords /= 2;

            // draw the line outline, is the polarity on?
            if (GetApertureIsOn(varArray) == false)
            {
                // we will need the center point coords
                PointF centerPoint = GetCenterPoint(varArray);
                int    primCenterPointInScreenCoords_X = (int)(centerPoint.X * stateMachine.IsoPlotPointsPerAppUnit);
                int    primCenterPointInScreenCoords_Y = (int)(centerPoint.Y * stateMachine.IsoPlotPointsPerAppUnit);

                int effectiveCenter_X = x1 + primCenterPointInScreenCoords_X;
                int effectiveCenter_Y = y1 + primCenterPointInScreenCoords_Y;

                // get the center points
                PointF centerPointLeft  = this.GetLeftCenterCoord(varArray, xyCompInPlotCoords, true);
                PointF centerPointRight = this.GetRightCenterCoord(varArray, xyCompInPlotCoords, true);
                // convert them to screen coords
                int leftCenterPointInScreenCoords_X  = (int)(centerPointLeft.X * stateMachine.IsoPlotPointsPerAppUnit);
                int leftCenterPointInScreenCoords_Y  = (int)(centerPointLeft.Y * stateMachine.IsoPlotPointsPerAppUnit);
                int rightCenterPointInScreenCoords_X = (int)(centerPointRight.X * stateMachine.IsoPlotPointsPerAppUnit);
                int rightCenterPointInScreenCoords_Y = (int)(centerPointRight.Y * stateMachine.IsoPlotPointsPerAppUnit);
                // now calc the effective draw points
                int effectiveLeftCenterPoint_X  = x1 + leftCenterPointInScreenCoords_X;
                int effectiveLeftCenterPoint_Y  = y1 + leftCenterPointInScreenCoords_Y;
                int effectiveRightCenterPoint_X = x1 + rightCenterPointInScreenCoords_X;
                int effectiveRightCenterPoint_Y = y1 + rightCenterPointInScreenCoords_Y;

                // adjust the line height for the XY comp, the width was compensated earlier
                int lineHeightInScreenCoordsXYCompensated = lineHeightInScreenCoords - (xyComp);

                // clear polarity
                builderID = isoPlotBuilder.DrawGSLineOutLine(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_INVERTEDGE, effectiveLeftCenterPoint_X, effectiveLeftCenterPoint_Y, effectiveRightCenterPoint_X, effectiveRightCenterPoint_Y, lineHeightInScreenCoordsXYCompensated, stateMachine.BackgroundFillModeAccordingToPolarity);

                // get the bounding box of this primitive
                RectangleF primBoundingBox = GetMacroPrimitiveBoundingBox(varArray);
                // convert to screen values, this is still the primitive bounding rect though
                RectangleF primBoundingBoxInScreenCoords = MiscGraphicsUtils.ConvertRectFToScreenCoordinates(primBoundingBox, stateMachine);
                // the bounding box is relative to the center coords we adjust to absolute
                int newX0 = (int)(effectiveCenter_X - (primBoundingBoxInScreenCoords.Width / 2));
                int newY0 = (int)(effectiveCenter_Y - (primBoundingBoxInScreenCoords.Height / 2));
                int newX1 = (int)(newX0 + primBoundingBoxInScreenCoords.Width);
                int newY1 = (int)(newY0 + primBoundingBoxInScreenCoords.Height);

                // now remove everything belonging to the macro at this point which is under our transparent flash
                isoPlotBuilder.EraseBuilderIDListFromRegionUsingABuilderIDHoriz(macroBuilderIDs, builderID, newX0, newY0, newX1, newY1, -1);

                // now remove the transparent flash INVERT_EDGE if it is not on something belonging to the macro. This prevents us
                // cutting through non macro material.
                isoPlotBuilder.EraseBuilderIDIfNotOnCellWithIDsInList(macroBuilderIDs, builderID, newX0, newY0, newX1, newY1);

                // we do NOT return the builder ID here only the ones which draw in positive get returned
                return(0);
            }
            else
            {
                // get the center points
                PointF centerPointLeft  = this.GetLeftCenterCoord(varArray, xyCompInPlotCoords, false);
                PointF centerPointRight = this.GetRightCenterCoord(varArray, xyCompInPlotCoords, false);
                // convert them to screen coords
                int leftCenterPointInScreenCoords_X  = (int)(centerPointLeft.X * stateMachine.IsoPlotPointsPerAppUnit);
                int leftCenterPointInScreenCoords_Y  = (int)(centerPointLeft.Y * stateMachine.IsoPlotPointsPerAppUnit);
                int rightCenterPointInScreenCoords_X = (int)(centerPointRight.X * stateMachine.IsoPlotPointsPerAppUnit);
                int rightCenterPointInScreenCoords_Y = (int)(centerPointRight.Y * stateMachine.IsoPlotPointsPerAppUnit);
                // now calc the effective draw points
                int effectiveLeftCenterPoint_X  = x1 + leftCenterPointInScreenCoords_X;
                int effectiveLeftCenterPoint_Y  = y1 + leftCenterPointInScreenCoords_Y;
                int effectiveRightCenterPoint_X = x1 + rightCenterPointInScreenCoords_X;
                int effectiveRightCenterPoint_Y = y1 + rightCenterPointInScreenCoords_Y;

                // adjust the line height for the XY comp, the width was compensated earlier
                int lineHeightInScreenCoordsXYCompensated = lineHeightInScreenCoords + (xyComp);

                // dark polarity
                builderID = isoPlotBuilder.DrawGSLineOutLine(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_NORMALEDGE, effectiveLeftCenterPoint_X, effectiveLeftCenterPoint_Y, effectiveRightCenterPoint_X, effectiveRightCenterPoint_Y, lineHeightInScreenCoordsXYCompensated, stateMachine.BackgroundFillModeAccordingToPolarity);
                return(builderID);
            }
        }
示例#25
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Flash a macro primitive for a Circle on a GCode Plot
        /// </summary>
        /// <param name="isoPlotBuilder">the builder opbject</param>
        /// <param name="stateMachine">the statemachine</param>
        /// <param name="macroBuilderIDs">a list of builder IDs which have drawn in POSITIVE on this macro</param>
        /// <param name="xyComp">the xy compensation factor</param>
        /// <param name="x1">the first x value</param>
        /// <param name="y1">the first y value</param>
        /// <param name="varArray">the array to get the numbered variables from</param>
        /// <returns>z success, nz fail</returns>
        public override int FlashMacroPrimitiveForGCodePlot(GerberMacroVariableArray varArray, List <int> macroBuilderIDs, IsoPlotBuilder isoPlotBuilder, GerberFileStateMachine stateMachine, int x1, int y1, int xyComp)
        {
            // now do the flash
            int builderID = 0;

            if (isoPlotBuilder == null)
            {
                return(-1);
            }
            if (stateMachine == null)
            {
                return(-1);
            }
            if (macroBuilderIDs == null)
            {
                return(-1);
            }

            // get the VertexPointArray converted and rotated
            PointF[] tmpPointArray = GetPointArrayAsPointFArray(varArray);
            // collect the vertexPoints we operate on here
            PointF[] vertexPoints = new PointF[vertexPointArray.Length];

            // loop through the tmpPointArray
            for (int i = 0; i < tmpPointArray.Length; i++)
            {
                //DebugMessage("rawPoint=" + tmpPointArray[i].ToString());

                // we will need them as screen coords
                float primPointInScreenCoords_X = tmpPointArray[i].X * stateMachine.IsoPlotPointsPerAppUnit;
                float primPointInScreenCoords_Y = tmpPointArray[i].Y * stateMachine.IsoPlotPointsPerAppUnit;

                // we can calc the effective draw point of the current primitive, we do it out here to make this obvious
                float effectiveDrawPoint_X = x1 + primPointInScreenCoords_X;
                float effectiveDrawPoint_Y = y1 + primPointInScreenCoords_Y;

                // create a new point and stuff it in the array
                vertexPoints[i] = new PointF(effectiveDrawPoint_X, effectiveDrawPoint_Y);
                //DebugMessage("  vertexPoint=" + vertexPoints[i].ToString());
            }

            if (GetApertureIsOn(varArray) == true)
            {
                // draw the circle

                builderID = isoPlotBuilder.DrawGSOutLine(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_NORMALEDGE, vertexPoints, stateMachine.BackgroundFillModeAccordingToPolarity);
                // return this, the caller keeps track of these
                return(builderID);
            }
            else
            {
                // draw the circle, we use invert edges here so we draw the circle only if it is on some other background, use no fill. We will erase between it and the hole later
                builderID = isoPlotBuilder.DrawGSOutLine(IsoPlotUsageTagFlagEnum.IsoPlotUsageTagFlag_INVERTEDGE, vertexPoints, GSFillModeEnum.FillMode_NONE);

                // now we have to remove every builderID in the macro in every isoCell under the above object. This is not fast.
                // We know which ones might be there because we have a list

                // we will need the center point coords
                int primCenterPointInScreenCoords_X = (int)(GetXCenterCoord(varArray) * stateMachine.IsoPlotPointsPerAppUnit);
                int primCenterPointInScreenCoords_Y = (int)(GetYCenterCoord(varArray) * stateMachine.IsoPlotPointsPerAppUnit);

                int effectiveCenter_X = x1 + primCenterPointInScreenCoords_X;
                int effectiveCenter_Y = y1 + primCenterPointInScreenCoords_Y;

                // get the bounding box of this primitive
                RectangleF primBoundingBox = GetMacroPrimitiveBoundingBox(varArray);
                // convert to screen values, this is still the primitive bounding rect though
                RectangleF primBoundingBoxInScreenCoords = MiscGraphicsUtils.ConvertRectFToScreenCoordinates(primBoundingBox, stateMachine);
                // the bounding box is relative to the center coords we adjust to absolute
                int newX0 = (int)(effectiveCenter_X - (primBoundingBoxInScreenCoords.Width / 2));
                int newY0 = (int)(effectiveCenter_Y - (primBoundingBoxInScreenCoords.Height / 2));
                int newX1 = (int)(newX0 + primBoundingBoxInScreenCoords.Width);
                int newY1 = (int)(newY0 + primBoundingBoxInScreenCoords.Height);

                // now remove everything belonging to the macro at this point which is under our transparent flash
                isoPlotBuilder.EraseBuilderIDListFromRegionUsingABuilderIDHoriz(macroBuilderIDs, builderID, newX0, newY0, newX1, newY1, -1);

                // now remove the transparent flash INVERT_EDGE if it is not on something belonging to the macro. This prevents us
                // cutting through non macro material.
                isoPlotBuilder.EraseBuilderIDIfNotOnCellWithIDsInList(macroBuilderIDs, builderID, newX0, newY0, newX1, newY1);

                // we do NOT return the builder ID here only the ones which draw in positive get returned
                return(0);
            }
        }
示例#26
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// We fill a shape with the macro primitive at the current coordinates.
        /// </summary>
        /// <param name="graphicsObj">a graphics object to draw on</param>
        /// <param name="workingBrush">a brush to draw with</param>
        /// <param name="bottomOfGraphicsObjInMacroScreenCoords_X">the macro screen coord which represents the bottom 0 coord of the graphics object</param>
        /// <param name="bottomOfGraphicsObjInMacroScreenCoords_Y">the macro screen coord which represents the bottom 0 coord of the graphics object</param>
        /// <param name="varArray">the array to get the numbered variables from</param>
        /// <returns>z success, nz fail</returns>
        public override void FlashMacroPrimitiveForGerberPlot(GerberFileStateMachine stateMachine, GerberMacroVariableArray varArray, Graphics graphicsObj, Brush workingBrush, float bottomOfGraphicsObjInMacroScreenCoords_X, float bottomOfGraphicsObjInMacroScreenCoords_Y)
        {
            if (graphicsObj == null)
            {
                return;
            }
            if (workingBrush == null)
            {
                return;
            }
            if (stateMachine == null)
            {
                return;
            }

            // note that the graphicsObj here is not the main screen. It is a smaller temporary graphics object
            // designed only to receive the macro. The underlying bitmap of this graphics object gets overlaid on the screen later

            // note the bottomOfGraphicsObjInMacroScreenCoords_? vars are not the bottom of this macro primitives space. It is the
            // screen coords of the bottom of the smallest rectangle which contains all of the macro primitives

            // get the bounding box of this primitive
            RectangleF primBoundingBox = GetMacroPrimitiveBoundingBox(varArray);
            // convert to screen values, this is still the primitive bounding rect though
            RectangleF primBoundingBoxInScreenCoords = MiscGraphicsUtils.ConvertRectFToScreenCoordinates(primBoundingBox, stateMachine);

            float workingWidth             = GetWidth(varArray);
            int   lineWidthInScreenCoords  = (int)Math.Round(workingWidth * stateMachine.IsoPlotPointsPerAppUnit);
            float workingHeight            = GetHeight(varArray);
            int   lineHeightInScreenCoords = (int)Math.Round(workingHeight * stateMachine.IsoPlotPointsPerAppUnit);

            // we will need the center point coords
            int primCenterPointInScreenCoords_X = (int)(GetXCenterCoord(varArray) * stateMachine.IsoPlotPointsPerAppUnit);
            int primCenterPointInScreenCoords_Y = (int)(GetYCenterCoord(varArray) * stateMachine.IsoPlotPointsPerAppUnit);

            //DebugMessage("  BX=(" + bottomOfGraphicsObjInMacroScreenCoords_X.ToString() + "," + bottomOfGraphicsObjInMacroScreenCoords_Y.ToString() + ")");
            //DebugMessage("  primBoundingBox=" + primBoundingBox.ToString());
            //DebugMessage("  primBoundingBoxInScreenCoords=" + primBoundingBoxInScreenCoords.ToString());
            //DebugMessage("  CPX,Y=(" + primCenterPointInScreenCoords_X.ToString() + "," + primCenterPointInScreenCoords_Y.ToString() + ")");

            // we can calc the effective center point of the current primitive, we do it out here to make this obvious
            int effectiveDrawPoint_X0 = (int)(primCenterPointInScreenCoords_X - bottomOfGraphicsObjInMacroScreenCoords_X);
            int effectiveDrawPoint_Y0 = (int)(primCenterPointInScreenCoords_Y - bottomOfGraphicsObjInMacroScreenCoords_Y);

            // get the center points
            PointF centerPointLeft  = this.GetLeftCenterCoord(varArray, 0, false);
            PointF centerPointRight = this.GetRightCenterCoord(varArray, 0, false);
            // convert them to screen coords
            int leftCenterPointInScreenCoords_X  = (int)(centerPointLeft.X * stateMachine.IsoPlotPointsPerAppUnit);
            int leftCenterPointInScreenCoords_Y  = (int)(centerPointLeft.Y * stateMachine.IsoPlotPointsPerAppUnit);
            int rightCenterPointInScreenCoords_X = (int)(centerPointRight.X * stateMachine.IsoPlotPointsPerAppUnit);
            int rightCenterPointInScreenCoords_Y = (int)(centerPointRight.Y * stateMachine.IsoPlotPointsPerAppUnit);
            // now calc the effective draw points
            int effectiveLeftCenterPoint_X  = (int)(leftCenterPointInScreenCoords_X - bottomOfGraphicsObjInMacroScreenCoords_X);
            int effectiveLeftCenterPoint_Y  = (int)(leftCenterPointInScreenCoords_Y - bottomOfGraphicsObjInMacroScreenCoords_Y);
            int effectiveRightCenterPoint_X = (int)(rightCenterPointInScreenCoords_X - bottomOfGraphicsObjInMacroScreenCoords_X);
            int effectiveRightCenterPoint_Y = (int)(rightCenterPointInScreenCoords_Y - bottomOfGraphicsObjInMacroScreenCoords_Y);

            //// Draw gerber line according to exposure
            Pen workingPen = GetDrawPen(stateMachine, varArray, lineHeightInScreenCoords);

            // simulate sweeping the aperture from one end of the line to the other
            graphicsObj.DrawLine(workingPen, effectiveLeftCenterPoint_X, effectiveLeftCenterPoint_Y, effectiveRightCenterPoint_X, effectiveRightCenterPoint_Y);
            if (workingPen != null)
            {
                workingPen.Dispose();
            }
        }
示例#27
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// We fill a shape with the macro primitive at the current coordinates.
        /// </summary>
        /// <param name="graphicsObj">a graphics object to draw on</param>
        /// <param name="workingBrush">a brush to draw with</param>
        /// <param name="bottomOfGraphicsObjInMacroScreenCoords_X">the macro screen coord which represents the bottom 0 coord of the graphics object</param>
        /// <param name="bottomOfGraphicsObjInMacroScreenCoords_Y">the macro screen coord which represents the bottom 0 coord of the graphics object</param>
        /// <param name="varArray">the array to get the numbered variables from</param>
        /// <returns>z success, nz fail</returns>
        public override void FlashMacroPrimitiveForGerberPlot(GerberFileStateMachine stateMachine, GerberMacroVariableArray varArray, Graphics graphicsObj, Brush workingBrush, float bottomOfGraphicsObjInMacroScreenCoords_X, float bottomOfGraphicsObjInMacroScreenCoords_Y)
        {
            if (graphicsObj == null)
            {
                return;
            }
            if (workingBrush == null)
            {
                return;
            }
            if (stateMachine == null)
            {
                return;
            }

            // note that the graphicsObj here is not the main screen. It is a smaller temporary graphics object
            // designed only to receive the macro. The underlying bitmap of this graphics object gets overlaid on the screen later

            // note the bottomOfGraphicsObjInMacroScreenCoords_? vars are not the bottom of this macro primitives space. It is the
            // screen coords of the bottom of the smallest rectangle which contains all of the macro primitives

            // get the bounding box of this primitive
            RectangleF primBoundingBox = GetMacroPrimitiveBoundingBox(varArray);
            // convert to screen values, this is still the primitive bounding rect though
            RectangleF primBoundingBoxInScreenCoords = MiscGraphicsUtils.ConvertRectFToScreenCoordinates(primBoundingBox, stateMachine);

            float workingDiameter = GetDiameter(varArray);
            int   circleDiameter  = (int)Math.Round(workingDiameter * stateMachine.IsoPlotPointsPerAppUnit);

            // we will need the center point coords
            int primCenterPointInScreenCoords_X = (int)(GetXCenterCoord(varArray) * stateMachine.IsoPlotPointsPerAppUnit);
            int primCenterPointInScreenCoords_Y = (int)(GetYCenterCoord(varArray) * stateMachine.IsoPlotPointsPerAppUnit);

            //DebugMessage("  BX=(" + bottomOfGraphicsObjInMacroScreenCoords_X.ToString() + "," + bottomOfGraphicsObjInMacroScreenCoords_Y.ToString() + ")");
            //DebugMessage("  primBoundingBox=" + primBoundingBox.ToString());
            //DebugMessage("  primBoundingBoxInScreenCoords=" + primBoundingBoxInScreenCoords.ToString());
            //DebugMessage("  CPX,Y=(" + primCenterPointInScreenCoords_X.ToString() + "," + primCenterPointInScreenCoords_Y.ToString() + ")");

            // we can calc the effective center point of the current primitive, we do it out here to make this obvious
            int effectiveDrawPoint_X0 = (int)(primCenterPointInScreenCoords_X - bottomOfGraphicsObjInMacroScreenCoords_X);
            int effectiveDrawPoint_Y0 = (int)(primCenterPointInScreenCoords_Y - bottomOfGraphicsObjInMacroScreenCoords_Y);

            // the above are points at the circle center, fix up to point at lower left for the draw rectangle
            effectiveDrawPoint_X0 = effectiveDrawPoint_X0 - circleDiameter / 2;
            effectiveDrawPoint_Y0 = effectiveDrawPoint_Y0 - circleDiameter / 2;

            // set the width and height
            int effectiveWidth  = circleDiameter; // this does not change
            int effectiveHeight = circleDiameter; // this does not change

            // create a defining rectangle for the circle we are to draw
            Rectangle boundingRect = new Rectangle((int)effectiveDrawPoint_X0, effectiveDrawPoint_Y0, effectiveWidth, effectiveHeight);

            //DebugMessage("  effectiveDrawPoint=(" + effectiveDrawPoint_X0.ToString() + "," + effectiveDrawPoint_Y0.ToString() + ")");
            //DebugMessage("  draw boundingRect=" + boundingRect.ToString());

            // figure out the brush. We do not use the one passed in, we can flash in in reverse here
            Brush tmpBrush = GetDrawBrush(stateMachine, varArray);

            // Now flash
            graphicsObj.FillEllipse(tmpBrush, boundingRect);
        }
示例#28
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// If we fill a shape with the aperture at the current coordinates. This
        /// simulates the aperture flash of a Gerber plotter
        /// </summary>
        /// <param name="graphicsObj">a graphics object to draw on</param>
        /// <param name="workingBrush">a brush to draw with</param>
        /// <param name="x1">the x center value</param>
        /// <param name="y1">the y center value</param>
        /// <returns>z success, nz fail</returns>
        public override void FlashApertureForGerberPlot(GerberFileStateMachine stateMachine, Graphics graphicsObj, Brush workingBrush, float x1, float y1)
        {
            if (graphicsObj == null)
            {
                return;
            }
            if (workingBrush == null)
            {
                return;
            }
            if (stateMachine == null)
            {
                return;
            }

            // get the macro AM code object for this aperture
            GerberLine_AMCode workingMacro = GetMacroObject(stateMachine);

            if (workingMacro == null)
            {
                throw new Exception("No macro definition found for name " + MacroName);
            }

            // get the largest bounding box for all primitives in the macro
            RectangleF boundingRectF = workingMacro.GetMacroPrimitivesBoundingBox(VariableArray);

            // note the bottom of this box is not the (0,0) point of any one primitive. It is also not
            // the (0,0) point of the macro.

            // convert to screen values, this is still the macro bounding rect though
            RectangleF boundingRectFInScreenCoord = MiscGraphicsUtils.ConvertRectFToScreenCoordinates(boundingRectF, stateMachine);

            // set up to create a bitmap we draw our primitives on, we convert our floats to int
            // the +1 here is to ensure we round up. The bounding box can be bigger, but smaller is bad
            // we can assume the width and height here are positive. This should have been checked much earlier
            int boundingWidth  = (int)(boundingRectFInScreenCoord.Width) + 1;
            int boundingHeight = (int)(boundingRectFInScreenCoord.Height) + 1;

            // create an appropriately sized bitmap
            Bitmap macroBitmap = new Bitmap(boundingWidth, boundingHeight);
            // get a graphics object from the bitmap. We use this to draw the macro
            Graphics macroGraphicsObj = Graphics.FromImage(macroBitmap);

            // fill the rectangle with a background color not normally used on Gerber plots
            macroGraphicsObj.FillRectangle(new SolidBrush(ApplicationColorManager.DEFAULT_MACRO_TRANSPARENT_COLOR), 0, 0, boundingWidth, boundingHeight);

            // for diagnostics
            //DebugTODO("remove this");
            //macroGraphicsObj.DrawEllipse(Pens.Maroon, 0, 0, 25, 25);

            //// we run through our primitive list in order and and flash
            foreach (GerberMacroPrimitive_Base primObj in workingMacro.MacroPrimitives)
            {
                primObj.FlashMacroPrimitiveForGerberPlot(stateMachine, VariableArray, macroGraphicsObj, workingBrush, boundingRectFInScreenCoord.X, boundingRectFInScreenCoord.Y);
            }

            // now we place the newly drawn macroBitmap on the screen, first create an int based rectangle
            // which describes the screen location in Gerber coord onto which we place the macro bitmap
            // x1 and y1 are already converted to Gerber coords and are the effective (0,0) point of the macro
            // however they are not the (0,0) ppoint of the place we draw. The aperture origin does not have to
            // be in the macro Bitmap

            // we make this obvious
            int effectiveDrawPoint_X0 = (int)(x1 + boundingRectFInScreenCoord.X);
            int effectiveDrawPoint_Y0 = (int)(y1 + boundingRectFInScreenCoord.Y);
            int effectiveWidth        = boundingWidth;  // this does not change
            int effectiveHeight       = boundingHeight; // this does not change

            // create a defining rectangle
            Rectangle boundingRect = new Rectangle((int)effectiveDrawPoint_X0, effectiveDrawPoint_Y0, effectiveWidth, effectiveHeight);

            // make the parts that did not get a macro primitive drawn on them transparent
            macroBitmap.MakeTransparent(ApplicationColorManager.DEFAULT_MACRO_TRANSPARENT_COLOR);
            // overlay the macro bitmap on our main gerber display
            graphicsObj.DrawImage(macroBitmap, boundingRect);

            return;
        }