private static void ApplyNetStateTransformation(Graphics graphics, GerberNetState netState) { // Apply scale factor. graphics.ScaleTransform((float)netState.ScaleA, (float)netState.ScaleB); // Apply offset. graphics.TranslateTransform((float)netState.OffsetA, (float)netState.OffsetB); // Apply mirror. switch (netState.MirrorState) { case GerberMirrorState.FlipA: graphics.ScaleTransform(-1.0f, 1.0f); break; case GerberMirrorState.FlipB: graphics.ScaleTransform(1.0f, -1.0f); break; case GerberMirrorState.FlipAB: graphics.ScaleTransform(-1.0f, -1.0f); break; default: break; } // Finally, apply axis select. if (netState.AxisSelect == GerberAxisSelect.SwapAB) { // Do this by rotating 270 degrees counterclockwise, then mirroring the Y axis. graphics.RotateTransform(90); graphics.ScaleTransform(1.0f, -1.0f); } }
public GerberNet(GerberImage gerberImage, GerberNet currentNet, GerberLevel level, GerberNetState netState) { if (level != null) { Level = level; } else { Level = currentNet.Level; } if (netState != null) { NetState = netState; } else { NetState = currentNet.NetState; } Label = String.Empty; //IsSelected = false; gerberImage.GerberNetList.Add(this); }
// Renders a gerber image to the specified graphics target. private static void RenderToTarget(Graphics graphics, GerberImage gerberImage, Collection <GerberNet> gerberNetList, GerberUserTransform userTransform, Color foreGroundColor, Color backGroundColor, bool invert) { float dx, dy; float startX, startY, stopX, stopY; float p1, p2, p3, p4, p5; int repeatX = 1, repeatY = 1; float repeatDistanceX = 0.0f, repeatDistanceY = 0.0f; Collection <SimplifiedApertureMacro> simplifiedMacroList; PointF startPoint, endPoint; RectangleF apertureRectangle; int netListIndex = 0; GerberNet currentNet = null; GerberLevel oldLevel = null; GerberNetState oldState = null; bool useClearOperator = false; bool invertPolarity = false; SolidBrush brush = new SolidBrush(foreGroundColor); Pen pen = new Pen(foreGroundColor); // Apply user supplied transforations. double scaleX = userTransform.ScaleX; double scaleY = userTransform.ScaleY; if (userTransform.MirrorAroundX) { scaleY *= -1; } if (userTransform.MirrorAroundY) { scaleX *= -1; } graphics.TranslateTransform((float)userTransform.TranslateX, (float)userTransform.TranslateY); graphics.ScaleTransform((float)scaleX, (float)scaleY); graphics.RotateTransform((float)userTransform.Rotation); // Apply initial image transformations. graphics.TranslateTransform((float)gerberImage.ImageInfo.ImageJustifyOffsetActualA, (float)gerberImage.ImageInfo.ImageJustifyOffsetActualB); graphics.TranslateTransform((float)gerberImage.ImageInfo.OffsetA, (float)gerberImage.ImageInfo.OffsetB); graphics.RotateTransform((float)gerberImage.ImageInfo.ImageRotation); invertPolarity = invert; if (gerberImage.ImageInfo.Polarity == GerberPolarity.Negative) { invertPolarity = !invertPolarity; } if (invertPolarity) { graphics.Clear(foreGroundColor); } else { pen.Color = brush.Color = foreGroundColor; } for (netListIndex = 0; netListIndex < gerberNetList.Count; GetNextRenderObject(gerberNetList, ref netListIndex)) { currentNet = gerberNetList[netListIndex]; if (currentNet.Level != oldLevel) { // Set the current net transformation and polarity. graphics.RotateTransform((float)currentNet.Level.Rotation); if (currentNet.Level.Polarity == GerberPolarity.Clear ^ invertPolarity) { pen.Color = brush.Color = backGroundColor; } else { pen.Color = brush.Color = foreGroundColor; } // Check for changes to step and repeat. repeatX = currentNet.Level.StepAndRepeat.X; repeatY = currentNet.Level.StepAndRepeat.Y; repeatDistanceX = (float)currentNet.Level.StepAndRepeat.DistanceX; repeatDistanceY = (float)currentNet.Level.StepAndRepeat.DistanceY; // Draw any knockout areas. if (currentNet.Level.Knockout.FirstInstance == true) { Color oldColor = foreGroundColor; if (currentNet.Level.Knockout.Polarity == GerberPolarity.Clear) { pen.Color = brush.Color = backGroundColor; } else { pen.Color = brush.Color = foreGroundColor; } GraphicsPath knockoutPath = new GraphicsPath(); PointF pf1 = new PointF((float)(currentNet.Level.Knockout.LowerLeftX - currentNet.Level.Knockout.Border), (float)(currentNet.Level.Knockout.LowerLeftY - currentNet.Level.Knockout.Border)); PointF pf2 = new PointF(pf1.X + (float)(currentNet.Level.Knockout.Width + (currentNet.Level.Knockout.Border * 2)), pf1.Y); PointF pf3 = new PointF(pf2.X, pf1.Y + (float)(currentNet.Level.Knockout.Height + (currentNet.Level.Knockout.Border * 2))); PointF pf4 = new PointF(pf1.X, pf3.Y); PointF[] points = new PointF[] { pf1, pf2, pf3, pf4 }; knockoutPath.AddLines(points); knockoutPath.CloseFigure(); graphics.FillPath(brush, knockoutPath); // Restore the polarity. pen.Color = brush.Color = oldColor; } ApplyNetStateTransformation(graphics, currentNet.NetState); oldLevel = currentNet.Level; } // Check if this is a new netstate. if (currentNet.NetState != oldState) { // A new state, so recalculate the new transformation matrix. ApplyNetStateTransformation(graphics, currentNet.NetState); oldState = currentNet.NetState; } for (int rx = 0; rx < repeatX; rx++) { for (int ry = 0; ry < repeatY; ry++) { float stepAndRepeatX = rx * repeatDistanceX; float stepAndRepeatY = ry * repeatDistanceY; startX = (float)currentNet.StartX + stepAndRepeatX; startY = (float)currentNet.StartY + stepAndRepeatY; stopX = (float)currentNet.StopX + stepAndRepeatX; stopY = (float)currentNet.StopY + stepAndRepeatY; switch (gerberNetList[netListIndex].Interpolation) { case GerberInterpolation.PolygonAreaStart: FillPolygonArea(graphics, brush, gerberNetList, netListIndex, stepAndRepeatX, stepAndRepeatY); continue; case GerberInterpolation.Deleted: continue; } switch (currentNet.ApertureState) { case GerberApertureState.On: switch (currentNet.Interpolation) { case GerberInterpolation.LinearX10: case GerberInterpolation.LinearX01: case GerberInterpolation.LinearX001: case GerberInterpolation.LinearX1: pen.SetLineCap(LineCap.Round, LineCap.Round, DashCap.Round); switch (gerberImage.ApertureArray[currentNet.Aperture].ApertureType) { case GerberApertureType.Circle: pen.Width = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[0]; startPoint = new PointF(startX, startY); endPoint = new PointF(stopX, stopY); graphics.DrawLine(pen, startPoint, endPoint); break; case GerberApertureType.Rectangle: dx = (float)(gerberImage.ApertureArray[currentNet.Aperture].Parameters[0] / 2); dy = (float)(gerberImage.ApertureArray[currentNet.Aperture].Parameters[1] / 2); if (startX > stopX) { dx = -dx; } if (startY > stopY) { dy = -dy; } using (GraphicsPath path = new GraphicsPath()) { path.AddLine(startX - dx, startY - dy, startX - dx, startY + dy); path.AddLine(startX - dx, startY + dy, stopX - dx, stopY + dy); path.AddLine(stopX - dx, stopY + dy, stopX + dx, stopY + dy); path.AddLine(stopX + dx, stopY + dy, stopX + dx, stopY - dy); path.AddLine(stopX + dx, stopY - dy, startX + dx, startY - dy); graphics.FillPath(brush, path); } break; // For now, just render ovals or polygons like a circle. case GerberApertureType.Oval: case GerberApertureType.Polygon: pen.Width = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[0]; startPoint = new PointF(startX, startY); endPoint = new PointF(stopX, stopY); graphics.DrawLine(pen, startPoint, endPoint); break; // Macros can only be flashed, so ignore any that might be here. default: break; } break; case GerberInterpolation.ClockwiseCircular: case GerberInterpolation.CounterClockwiseCircular: float centerX = (float)currentNet.CircleSegment.CenterX; float centerY = (float)currentNet.CircleSegment.CenterY; float width = (float)currentNet.CircleSegment.Width; float height = (float)currentNet.CircleSegment.Height; float startAngle = (float)currentNet.CircleSegment.StartAngle; float sweepAngle = (float)currentNet.CircleSegment.SweepAngle; if (gerberImage.ApertureArray[currentNet.Aperture].ApertureType == GerberApertureType.Rectangle) { pen.SetLineCap(LineCap.Square, LineCap.Square, DashCap.Flat); } else { pen.SetLineCap(LineCap.Round, LineCap.Round, DashCap.Round); } RectangleF arcRectangle = new RectangleF(centerX - (width / 2), centerY - (height / 2), width, height); pen.Width = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[0]; if (arcRectangle != RectangleF.Empty) { graphics.DrawArc(pen, arcRectangle, startAngle, sweepAngle); } break; default: break; } break; case GerberApertureState.Flash: p1 = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[0]; p2 = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[1]; p3 = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[2]; p4 = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[3]; p5 = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[4]; GraphicsState state = graphics.Save(); graphics.TranslateTransform(stopX, stopY); using (GraphicsPath path = new GraphicsPath()) { switch (gerberImage.ApertureArray[currentNet.Aperture].ApertureType) { case GerberApertureType.Circle: apertureRectangle = new RectangleF(-(p1 / 2), -(p1 / 2), p1, p1); path.AddEllipse(apertureRectangle); DrawAperatureHole(path, p2, p3); break; case GerberApertureType.Rectangle: apertureRectangle = new RectangleF(-(p1 / 2), -(p2 / 2), p1, p2); path.AddRectangle(apertureRectangle); DrawAperatureHole(path, p3, p4); break; case GerberApertureType.Oval: apertureRectangle = new RectangleF(-(p1 / 2), -(p2 / 2), p1, p2); CreateOblongPath(path, p1, p2); DrawAperatureHole(path, p3, p4); break; case GerberApertureType.Polygon: CreatePolygon(graphics, path, p1, p2, p3); DrawAperatureHole(path, p4, p5); break; case GerberApertureType.Macro: simplifiedMacroList = gerberImage.ApertureArray[currentNet.Aperture].SimplifiedMacroList; useClearOperator = gerberImage.ApertureArray[currentNet.Aperture].Parameters[0] == 1.0 ? true : false; DrawApertureMacro(graphics, simplifiedMacroList, brush.Color, backGroundColor, useClearOperator); break; default: break; } graphics.FillPath(brush, path); // Fill the path. graphics.Restore(state); } break; default: break; } } } } pen.Dispose(); brush.Dispose(); }