Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.Fonts;
using System.Numerics;
using GerberLibrary.Core;
using GerberLibrary.Core.Primitives;
using Pen = GerberLibrary.Core.Primitives.Pen;
using SolidBrush = GerberLibrary.Core.Primitives.SolidBrush;
using GraphicsPath = GerberLibrary.Core.Primitives.GraphicsPath;
using FontFamily = GerberLibrary.Core.Primitives.FontFamily;
using FontStyle = GerberLibrary.Core.Primitives.FontStyle;
using StringFormat = GerberLibrary.Core.Primitives.StringFormat;
using GerberLibrary.EagleXML;
namespace GerberLibrary
{
namespace Eagle
{
public class ShapeInstance
{
public ShapeContainer TheShape;
public bool TopSide = true;
public PointF Position = new PointF(0, 0);
public double Rotation = 0;
public Bounds Bounds;
internal PointF Centroid;
public EagleLoader.DevicePlacement Placement;
}
public class Layer
{
}
public class Bounds
{
public double minx;
public double miny;
public double maxx;
public double maxy;
public int fitpoints = 0;
public void Fit(double x, double y)
{
if (fitpoints == 0)
{
minx = maxx = x;
miny = maxy = y;
}
else
{
if (x < minx) minx = x; else if (x > maxx) maxx = x;
if (y < miny) miny = y; else if (y > maxy) maxy = y;
}
fitpoints++;
}
public double Width()
{
return maxx - minx;
}
public void Clear()
{
fitpoints = 0;
}
public double Height()
{
return maxy - miny;
}
}
public class BoardRenderer
{
public static Color SilkColor = Color.White;
public static Color SMTColor = Color.DarkGray;
public static Color PADColor = Color.DarkGreen;
public static Color CopperColor = Color.Gold;
public static Color SymbolsColor = Color.DarkRed;
public static Bounds GetShapeBounds(ShapeContainer a)
{
Bounds R = new Bounds();
foreach (var s in a.Shapes)
{
var Ps = s.GetPolygons();
foreach (var P in Ps)
{
foreach (var v in P)
{
R.Fit(v.X, v.Y);
}
}
}
return R;
}
public static Color DrillColor = Color.Black;
public static Color DocuColor = Color.FromRgba(255, 255, 0, 200); // ImageSharp Color.FromRgba(r,g,b,a)
Dictionary<LayerSpec, Color> Colors = new Dictionary<LayerSpec, Color>();
Dictionary<LayerSpec, int> LayerPriority = new Dictionary<LayerSpec, int>();
Dictionary<LayerSpec, List<DisplayString>> StringsPerLayer = new Dictionary<LayerSpec, List<DisplayString>>();
List<PointF> debugpoints = new List<PointF>();
Dictionary<LayerSpec, int> Layers = new Dictionary<LayerSpec, int>();
Dictionary<LayerSpec, List<List<Tuple<SchematicNet, List<PointF>>>>> ShapeLists = new Dictionary<LayerSpec, List<List<Tuple<SchematicNet, List<PointF>>>>>();
public GerberLibrary.Bounds Bounds = new GerberLibrary.Bounds();
public float GetScale(double MaxW, double MaxH)
{
double aspect = MaxW / MaxH;
double dispw = Bounds.Width();
double disph = Bounds.Height();
double scale = 1.0;
double partaspect = dispw / disph;
if (partaspect > aspect)
{
scale = (MaxW) / (dispw + 3);
}
else
{
scale = (MaxH) / (disph + 3);
}
return (float)scale;
}
public Matrix3x2 Getmatrix(double MaxW, double MaxH, double scalefac = 1.0, double xoff = 0, double yoff = 0)
{
double minx = Bounds.TopLeft.X;
double maxx = Bounds.BottomRight.X;
double miny = Bounds.TopLeft.Y;
double maxy = Bounds.BottomRight.Y;
double aspect = MaxW / MaxH;
double dispw = maxx - minx;
double disph = maxy - miny;
double scale = 1.0;
double partaspect = dispw / disph;
if (partaspect > aspect)
{
scale = (MaxW) / (dispw + 3);
}
else
{
scale = (MaxH) / (disph + 3);
}
// Reverse order of GDI+ operations for Matrix3x2
Matrix3x2 mat = Matrix3x2.CreateScale((float)scalefac) *
Matrix3x2.CreateTranslation((float)xoff, (float)yoff) *
Matrix3x2.CreateTranslation((float)(-(maxx + minx) / 2), (float)((-(maxy + miny) / 2))) *
Matrix3x2.CreateScale((float)scale, (float)-scale) *
Matrix3x2.CreateTranslation((float)(MaxW / 2), (float)(MaxH / 2));
return mat;
}
public void DrawInstances(GerberLibrary.Core.GraphicsInterface g, double MaxW, double MaxH, bool rendergrid, Color gridcolor, double scalefac = 1.0, double xoff = 0, double yoff = 0)
{
double minx = Bounds.TopLeft.X;
double maxx = Bounds.BottomRight.X;
double miny = Bounds.TopLeft.Y;
double maxy = Bounds.BottomRight.Y;
double aspect = MaxW / MaxH;
double dispw = maxx - minx;
double disph = maxy - miny;
double scale = 1.0;
double partaspect = dispw / disph;
if (partaspect > aspect)
{
scale = (MaxW) / (dispw + 3);
}
else
{
scale = (MaxH) / (disph + 3);
}
if (dispw == 0 || disph == 0) return;
var originaltransform = g.Transform;
g.TranslateTransform((float)((MaxW) / 2), (float)((MaxH) / 2));
g.ScaleTransform((float)scale, (float)-scale);
g.TranslateTransform((float)(-(maxx + minx) / 2), (float)((-(maxy + miny) / 2)));
g.TranslateTransform((float)xoff, (float)yoff);
g.ScaleTransform((float)scalefac, (float)scalefac);
if (rendergrid)
{
Pen Thick = new Pen(gridcolor, (float)(2.0 / scale));
Pen Thin = new Pen(gridcolor, (float)(1.0 / scale));
for (int x = (int)minx - 10; x < (int)maxx + 10; x++)
{
g.DrawLine((x % 5 == 0) ? Thick : Thin, new PointF(x, (float)miny - 10), new PointF(x, (float)maxy + 10));
}
for (int y = (int)miny - 10; y < (int)maxy + 10; y++)
{
g.DrawLine((y % 5 == 0) ? Thick : Thin, new PointF((float)minx - 10, (float)y), new PointF((float)maxx + 10, (float)y));
}
}
// StringFormat SF = new StringFormat();
foreach (var l in (from i in Layers orderby i.Value select i.Key))
{
var L = ShapeLists[l];
Color C = Color.FromRgba(0, 10, 255, 100);
if (Colors.ContainsKey(l))
{
var c = Colors[l];
// C = Color.FromArgb(200, c); // alpha, basecolor
C = Color.FromRgba(c.ToPixel<Rgba32>().R, c.ToPixel<Rgba32>().G, c.ToPixel<Rgba32>().B, 200);
}
foreach (var p in L)
{
if (p.Count > 0)
{
// g.DrawPolygon(new Pen(C, (float)(1.0 / scale)), p.ToArray());
PathBuilder pb = new PathBuilder();
foreach (var P in p)
{
if (P.Item2.Count > 2)
pb.AddLines(P.Item2.Select(pt => new PointF(pt.X, pt.Y)).ToArray());
}
g.FillPath(new SolidBrush(C), pb.Build());
}
}
foreach (var S in StringsPerLayer[l])
{
TextOptions options = new TextOptions(SystemFonts.CreateFont("Arial", (float)S.size));
switch (S.alignment)
{
case textAlign.center: options.HorizontalAlignment = HorizontalAlignment.Center; options.VerticalAlignment = VerticalAlignment.Center; break;
case textAlign.centerleft: options.HorizontalAlignment = HorizontalAlignment.Left; options.VerticalAlignment = VerticalAlignment.Center; break;
case textAlign.centerright: options.HorizontalAlignment = HorizontalAlignment.Right; options.VerticalAlignment = VerticalAlignment.Center; break;
case textAlign.topcenter: options.HorizontalAlignment = HorizontalAlignment.Center; options.VerticalAlignment = VerticalAlignment.Top; break;
case textAlign.topleft: options.HorizontalAlignment = HorizontalAlignment.Left; options.VerticalAlignment = VerticalAlignment.Top; break;
case textAlign.topright: options.HorizontalAlignment = HorizontalAlignment.Right; options.VerticalAlignment = VerticalAlignment.Top; break;
case textAlign.bottomcenter: options.HorizontalAlignment = HorizontalAlignment.Center; options.VerticalAlignment = VerticalAlignment.Bottom; break;
case textAlign.bottomleft: options.HorizontalAlignment = HorizontalAlignment.Left; options.VerticalAlignment = VerticalAlignment.Bottom; break;
case textAlign.bottomright: options.HorizontalAlignment = HorizontalAlignment.Right; options.VerticalAlignment = VerticalAlignment.Bottom; break;
}
options.Origin = new PointF((float)S.x, (float)S.y);
g.DrawString(S.Text, options.Font, new SolidBrush(C), options.Origin, options);
}
}
foreach (var a in debugpoints)
{
g.DrawRectangle(new Pen(Color.GreenYellow, 0.01f), a.X - .01f, a.Y - .01f, .02f, .02f);
}
g.Transform = originaltransform;
g.TranslateTransform((float)((MaxW) / 2), (float)((MaxH) / 2));
g.ScaleTransform((float)scale, (float)scale);
g.TranslateTransform((float)(-(maxx + minx) / 2), (float)((-(maxy + miny) / 2)));
// g.InterpolationMode = InterpolationMode.High;
if (false)
foreach (var l in (from i in Layers orderby i.Value select i.Key))
{
var L = ShapeLists[l];
foreach (var p in L)
{
foreach (var P in p)
{
if (P.Item1 != null && P.Item1.Name != null)
{
var PS = PolyCenter(P.Item2);
GraphicsPath PATH = new GraphicsPath();
PATH.AddString(
P.Item1.Name, // text to draw
FontFamily.GenericSansSerif, // or any other font family
(int)FontStyle.Regular, // font style (bold, italic, etc.)
72 * 10.0f / (72 * (float)scale), // em size
new PointF(PS.X, (float)maxy - (PS.Y - (float)miny)), // location where to draw text
new StringFormat()); // set options here (e.g. center alignment)
g.DrawPath(new Pen(Color.Black, 2.0f / (float)scale), new PathBuilder().Build());
g.FillPath(new SolidBrush(Color.White), new PathBuilder().Build());
//g.DrawString(P.Item1.Name, new Font("Arial", 0.2f), Brushes.Black,, new StringFormat());
}
}
}
}
}
private PointF PolyCenter(List<PointF> points)
{
if (points.Count > 0)
{
float x = 0;
float y = 0;
for (int i = 0; i < points.Count; i++)
{
x += points[i].X;
y += points[i].Y;
}
x /= (float)points.Count;
y /= (float)points.Count;
return new PointF(x, y);
}
return new PointF(0, 0);
}
public void PrepareInstances(List<ShapeInstance> Instances, BoardSpec BS, bool showtext = true)
{
Colors[LayerSpec.ParseLayer("PADS", BS.Layers, LayerType.Copper)] = PADColor;
Colors[LayerSpec.ParseLayer("1", BS.Layers)] = CopperColor;
Colors[LayerSpec.ParseLayer("TOPCOPPER", BS.Layers, LayerType.Copper)] = CopperColor;
Colors[LayerSpec.ParseLayer("BOTHCOPPER", BS.Layers, LayerType.Copper)] = CopperColor;
Colors[LayerSpec.ParseLayer("BOTTOMCOPPER", BS.Layers, LayerType.Copper)] = CopperColor;
Colors[LayerSpec.ParseLayer("DRILL", BS.Layers)] = DrillColor;
Colors[LayerSpec.ParseLayer("DRILLS", BS.Layers)] = DrillColor;
/*Colors[LayerSpec.ParseLayer("16", BS.Layers)] = CopperColor;
Colors[LayerSpec.ParseLayer("21", BS.Layers)] = SilkColor;
Colors[LayerSpec.ParseLayer("51", BS.Layers)] = DocuColor;
Colors[LayerSpec.ParseLayer("52", BS.Layers)] = DocuColor;
Colors[LayerSpec.ParseLayer("22", BS.Layers)] = SilkColor;
Colors[LayerSpec.ParseLayer("25", BS.Layers)] = SilkColor;
Colors[LayerSpec.ParseLayer("26", BS.Layers)] = SilkColor;
Colors[LayerSpec.ParseLayer("27", BS.Layers)] = SilkColor;
Colors[LayerSpec.ParseLayer("28", BS.Layers)] = SilkColor;
Colors[LayerSpec.ParseLayer("94", BS.Layers)] = SymbolsColor;*/
foreach (var a in BS.Layers)
{
switch (a.type)
{
case LayerType.Copper: Colors[a] = CopperColor; break;
case LayerType.Silk: Colors[a] = SilkColor; break;
case LayerType.Docu: Colors[a] = DocuColor; break;
case LayerType.Drill: Colors[a] = DrillColor; break;
}
}
LayerPriority[LayerSpec.ParseLayer("21", BS.Layers)] = 100;
LayerPriority[LayerSpec.ParseLayer("22", BS.Layers)] = 100;
LayerPriority[LayerSpec.ParseLayer("25", BS.Layers)] = 100;
LayerPriority[LayerSpec.ParseLayer("26", BS.Layers)] = 100;
LayerPriority[LayerSpec.ParseLayer("27", BS.Layers)] = 100;
LayerPriority[LayerSpec.ParseLayer("28", BS.Layers)] = 100;
LayerPriority[LayerSpec.ParseLayer("51", BS.Layers)] = 101;
LayerPriority[LayerSpec.ParseLayer("52", BS.Layers)] = 101;
LayerPriority[LayerSpec.ParseLayer("DRILL", BS.Layers)] = 200;
LayerPriority[LayerSpec.ParseLayer("DRILLS", BS.Layers)] = 200;
LayerPriority[LayerSpec.ParseLayer("TOPCOPPER", BS.Layers, LayerType.Copper)] = 90;
LayerPriority[LayerSpec.ParseLayer("BOTTOMCOPPER", BS.Layers, LayerType.Copper)] = 90;
LayerPriority[LayerSpec.ParseLayer("BOTHCOPPER", BS.Layers, LayerType.Copper)] = 90;
int count = 0;
int vertexcount = 0;
foreach (var I in Instances)
{
if (I.Bounds == null) I.Bounds = GetInstanceBounds(I);
var ThePackage = I.TheShape;
foreach (var a in ThePackage.Shapes)
{
LayerSpec layer = a.GetLayer();
if (Layers.ContainsKey(layer) == false)
{
Layers[layer] = 1;
if (LayerPriority.ContainsKey(layer)) Layers[layer] = LayerPriority[layer];
ShapeLists[layer] = new List<List<Tuple<SchematicNet, List<PointF>>>>();
count++;
}
}
Matrix3x2 R = Matrix3x2.Identity;
R = Matrix3x2.CreateTranslation((float)I.Position.X, (float)I.Position.Y) * R;
if (I.TopSide == false)
{
R = Matrix3x2.CreateScale(-1, 1) * R;
}
R = Matrix3x2.CreateRotation((float)(I.Rotation * Math.PI / 180.0)) * R;
foreach (var a in ThePackage.Shapes)
{
SchematicNet ShapeSignal = null;
if (I.Placement != null && I.Placement.Pins.ContainsKey(a.Name))
{
ShapeSignal = I.Placement.Pins[a.Name].signal;
}
var DBP = a.GetDebugPoints().ToArray();
var PolySet = new List<Tuple<SchematicNet, List<PointF>>>();
bool process = true;
if (a as TextShape != null && showtext == false)
{ process = false; }
if (process)
foreach (var Ps in a.GetPolygons())
{
double minx = 0;
double miny = 0;
double maxx = 0;
double maxy = 0; ;
var P = Ps.ToArray();
for (int i = 0; i < P.Count(); i++)
{
PointF rotP = new PointF(P[i].X, P[i].Y);
rotP = Vector2.Transform(rotP, R);
P[i].X = rotP.X;
P[i].Y = rotP.Y;
Bounds.FitPoint(P[i].X, P[i].Y);
if (vertexcount == 0)
{
minx = maxx = P[i].X;
miny = maxy = P[i].Y;
}
else
{
if (P[i].X < minx) minx = P[i].X; else if (P[i].X > maxx) maxx = P[i].X;
if (P[i].Y < miny) miny = P[i].Y; else if (P[i].Y > maxy) maxy = P[i].Y;
}
vertexcount++;
}
I.Centroid = new PointF((float)(minx + maxx) / 2, (float)(miny + maxy) / 2);
PolySet.Add(new Tuple<SchematicNet, List<PointF>>(ShapeSignal, P.ToList()));
}
if (StringsPerLayer.ContainsKey(a.GetLayer()) == false) StringsPerLayer[a.GetLayer()] = new List<DisplayString>();
foreach (var ds in a.DisplayStrings)
{
StringsPerLayer[a.GetLayer()].Add(new DisplayString() { alignment = ds.alignment, size = ds.size, x = ds.x + I.Position.X, Text = ds.Text, y = ds.y + I.Position.Y });
}
ShapeLists[a.GetLayer()].Add(PolySet);
for (int i = 0; i < DBP.Count(); i++)
{
DBP[i].X += I.Position.X;
DBP[i].Y += I.Position.Y;
}
debugpoints.AddRange(DBP.ToList());
}
}
if (count == 0) return;
foreach (var l in ShapeLists.Values)
{
foreach (var k in l)
{
foreach (var q in k)
{
foreach (var p in q.Item2)
{
Bounds.FitPoint(p.X, p.Y);
}
}
}
}
}
private Bounds GetInstanceBounds(ShapeInstance i)
{
return GetShapeBounds(i.TheShape);
}
}
}
}
5203ce801This file is pinned to the selected release. Download the original to open it in your design tool.