private void testToolStripMenuItem_Click(object sender, EventArgs e) { SetActiveContainer(null); var schLib = new SchLib { new SchComponent { new SchRectangle { Corner = CoordPoint.FromMils(500, 1100) }, new SchPin { Location = CoordPoint.FromMils(500, 100) }, new SchPin { Location = CoordPoint.FromMils(500, 250) }, new SchPin { Location = CoordPoint.FromMils(500, 400) }, new SchPin { Location = CoordPoint.FromMils(500, 550) }, new SchPin { Location = CoordPoint.FromMils(500, 700) }, new SchPin { Location = CoordPoint.FromMils(500, 850) }, new SchPin { Location = CoordPoint.FromMils(500, 1000) }, new SchPin { Designator = "P8", Location = CoordPoint.FromMils(0, 1000), Orientation = TextOrientations.Flipped }, new SchPin { Location = CoordPoint.FromMils(0, 850), Orientation = TextOrientations.Flipped }, new SchPin { Location = CoordPoint.FromMils(0, 700), Orientation = TextOrientations.Flipped }, new SchPin { Location = CoordPoint.FromMils(0, 550), Orientation = TextOrientations.Flipped }, new SchPin { Location = CoordPoint.FromMils(0, 400), Orientation = TextOrientations.Flipped }, new SchPin { Location = CoordPoint.FromMils(0, 250), Orientation = TextOrientations.Flipped }, new SchPin { Location = CoordPoint.FromMils(0, 100), Orientation = TextOrientations.Flipped } } }; SetData(schLib); }
private void testPcbLibCreationToolStripMenuItem_Click(object sender, EventArgs e) { SetActiveContainer(null); var pcbLib = new PcbLib { new PcbComponent { new PcbMetaTrack( CoordPoint.FromMils(0, 0), CoordPoint.FromMils(1000, 0), CoordPoint.FromMils(1000, 1000), CoordPoint.FromMils(0, 1000), CoordPoint.FromMils(0, 0)), new PcbPad { Location = CoordPoint.FromMils(250, 100) }, new PcbPad { Location = CoordPoint.FromMils(500, 100) }, new PcbPad { Location = CoordPoint.FromMils(750, 100) }, new PcbPad(PcbPadTemplate.SmtTop) { Location = CoordPoint.FromMils(200, 750), SizeTop = CoordPoint.FromMils(80, 180) }, new PcbPad(PcbPadTemplate.SmtTop) { Location = CoordPoint.FromMils(400, 800), SizeTop = CoordPoint.FromMils(80, 180) }, new PcbPad(PcbPadTemplate.SmtTop) { Location = CoordPoint.FromMils(600, 800), SizeTop = CoordPoint.FromMils(80, 180) }, new PcbPad(PcbPadTemplate.SmtTop) { Location = CoordPoint.FromMils(800, 750), SizeTop = CoordPoint.FromMils(80, 180) }, new PcbVia { Location = CoordPoint.FromMils(50, 800) }, new PcbFill { Corner1 = CoordPoint.FromMils(200, 200), Corner2 = CoordPoint.FromMils(800, 600) } } }; SetData(pcbLib); }
private static List <CoordPoint> TrackPointsToListXY(string points, double zeroX, double zeroY) { string[] pointsArray = points.Split(' '); if ((pointsArray.Length % 2) == 1) { return(new List <CoordPoint>()); } var tmp = new List <CoordPoint>(); for (int i = 0; i < pointsArray.Length; i += 2) { double.TryParse(pointsArray[i], out double x); double.TryParse(pointsArray[i + 1], out double y); x -= zeroX; y -= zeroY; y = 0 - y; tmp.Add(CoordPoint.FromMils((Coord)LCSCcoordToMil(x), (Coord)LCSCcoordToMil(y))); } return(tmp); }
/// <summary> /// Detects rectangles from 4 consecutive lines that are connected. /// </summary> /// <param name="data">List of items in the schematic symbol.</param> /// <param name="dataIndex">Index of the first line to be tested for being part of a rectangle.</param> /// <param name="rectangle">Resulting rectangle.</param> /// <returns>Returns if a rectangle was found starting at index <paramref name="dataIndex"/></returns> private static bool DetectRectangle(List <LibItem> data, int dataIndex, out SchRectangle rectangle) { rectangle = null; bool LineMatches(Point testPoint, LibLine line, out Point otherPoint) { // tests if the point given matches the origin or end-point of the given line, returning the other point of the line if (testPoint == line.Origin) { otherPoint = line.EndPoint; return(true); } else if (testPoint == line.EndPoint) { otherPoint = line.Origin; return(true); } else { otherPoint = default; return(false); } } bool AreLinesConnected(params LibLine[] lines) { // see if starting from the origin of the first line we can find a sequence of points that go through all the 4 lines. var visited = new HashSet <LibLine>(); var currentPoint = lines[0].Origin; for (int n = 0, i = 0; n < lines.Length - 1; ++n) { visited.Add(lines[i]); Point nextPoint = default; i = Array.FindIndex(lines, l => !visited.Contains(l) && LineMatches(currentPoint, l, out nextPoint)); if (i == -1) { return(false); } currentPoint = nextPoint; } return(true); } (CoordPoint, CoordPoint) ExtremePoints(params LibLine[] lines) { var points = lines.Select(l1 => l1.Origin).Concat(lines.Select(l2 => l2.EndPoint)).ToList(); var c0 = CoordPoint.FromMils(points.Min(p => p.X), points.Min(p => p.Y)); var c1 = CoordPoint.FromMils(points.Max(p => p.X), points.Max(p => p.Y)); return(c0, c1); } if ((dataIndex < data.Count - 3) && data[dataIndex + 0] is LibLine libLine0 && data[dataIndex + 1] is LibLine libLine1 && data[dataIndex + 2] is LibLine libLine2 && data[dataIndex + 3] is LibLine libLine3 && AreLinesConnected(libLine0, libLine1, libLine2, libLine3)) { var(location, corner) = ExtremePoints(libLine0, libLine1, libLine2, libLine3); rectangle = new SchRectangle { Location = location, Corner = corner, LineWidth = ConvertWidth(libLine0.Width), }; return(true); } return(false); }
/// <summary> /// Converts a BxlSharp point to AltiumSharp /// </summary> private static CoordPoint ConvertPoint(Point point) { return(CoordPoint.FromMils(point.X, point.Y)); }
public static PcbComponent FootprintResponseToPcbComponent(FootprintResponse component) { var pcbComp = new PcbComponent(); //calc offset for zero string p1 = component.dataStr.shape.FirstOrDefault(c => c.Split('~')[(int)PADoffsets.command] == "PAD"); string[] p1Array = p1.Split('~'); double.TryParse(p1Array[(int)PADoffsets.center_x], out double zero_x); double.TryParse(p1Array[(int)PADoffsets.center_y], out double zero_y); //iterate over pads foreach (var item in component.dataStr.shape) { string[] shape = item.Split('~'); if (shape[0] == "PAD") { double.TryParse(shape[(int)PADoffsets.center_x], out double center_x); double.TryParse(shape[(int)PADoffsets.center_y], out double center_y); double.TryParse(shape[(int)PADoffsets.width], out double size_x); double.TryParse(shape[(int)PADoffsets.height], out double size_y); double.TryParse(shape[(int)PADoffsets.rotation], out double rotationAngle); Coord HoleSize = 0; PcbPadHoleShape HoleShape = PcbPadHoleShape.Round; Coord HoleSlotLengthCoord = 0; int holeAngle = 0; PcbPadTemplate padTemplate = PcbPadTemplate.Tht; if (LCSCLayerAltiumLayerMap[shape[(int)PADoffsets.layer_id]] == Layer.MultiLayer) { padTemplate = PcbPadTemplate.Tht; double.TryParse(shape[(int)PADoffsets.hole_radius], out double hole_radius); HoleSize = Coord.FromMils(LCSCcoordToMil(hole_radius)) * 2; if (shape[(int)PADoffsets.Hole_Length] != "") { double.TryParse(shape[(int)PADoffsets.Hole_Length], out double HoleSlotLength); if (HoleSlotLength > 0) { HoleShape = PcbPadHoleShape.Slot; HoleSlotLengthCoord = Coord.FromMils(LCSCcoordToMil(HoleSlotLength)); holeAngle = 270; } } } else { padTemplate = LCSCLayerAltiumLayerMap[shape[(int)PADoffsets.layer_id]] == Layer.TopLayer ? PcbPadTemplate.SmtTop : PcbPadTemplate.SmtBottom; } pcbComp.Add(new PcbPad(padTemplate) { Layer = LCSCLayerAltiumLayerMap[shape[(int)PADoffsets.layer_id]], Location = CoordPoint.FromMils(LCSCcoordToMil(center_x - zero_x), 0 - LCSCcoordToMil(center_y - zero_y)), Designator = shape[(int)PADoffsets.Designator], SizeTop = CoordPoint.FromMils(LCSCcoordToMil(size_x), LCSCcoordToMil(size_y)), Rotation = rotationAngle, SolderMaskExpansion = Coord.FromMils(4),//TODO implement recognition of solder mask expansion Shape = LCSCshapeToAltium(shape[(int)PADoffsets.shape]), HoleSize = HoleSize, HoleShape = HoleShape, HoleSlotLength = HoleSlotLengthCoord, HoleRotation = holeAngle, IsPlated = shape[(int)PADoffsets.Plated] == "Y" }); } else if (shape[0] == "ARC") { double.TryParse(shape[(int)ARCoffsets.stroke_width], out double stroke_width); if (LCSCarcConverter.TryParseArcPath(shape[(int)ARCoffsets.path_string], out LCSCarcConverter.SvgArcPath svgArc) != true) { throw new Exception("failed to parse arc parameters"); } var arc = LCSCarcConverter.SvgArcPathToArc(svgArc); pcbComp.Add(new PcbArc { Layer = LCSCLayerAltiumLayerMap[shape[(int)ARCoffsets.layer_id]], Location = CoordPoint.FromMils(LCSCcoordToMil(arc.center_x - zero_x), 0 - LCSCcoordToMil(arc.center_y - zero_y)), Width = Coord.FromMils(LCSCcoordToMil(stroke_width)), Radius = Coord.FromMils(LCSCcoordToMil(arc.radius)), StartAngle = arc.endAngle, EndAngle = arc.startAngle }); } else if (shape[0] == "CIRCLE") { double.TryParse(shape[(int)CIRCLEoffsets.center_x], out double center_x); double.TryParse(shape[(int)CIRCLEoffsets.center_y], out double center_y); double.TryParse(shape[(int)CIRCLEoffsets.stroke_width], out double stroke_width); double.TryParse(shape[(int)CIRCLEoffsets.radius], out double radius); pcbComp.Add(new PcbArc { Layer = LCSCLayerAltiumLayerMap[shape[(int)CIRCLEoffsets.layer_id]], Location = CoordPoint.FromMils(LCSCcoordToMil(center_x - zero_x), 0 - LCSCcoordToMil(center_y - zero_y)), Width = Coord.FromMils(LCSCcoordToMil(stroke_width)), Radius = Coord.FromMils(LCSCcoordToMil(radius)), StartAngle = 0, EndAngle = 360 }); } else if (shape[0] == "HOLE") { double.TryParse(shape[(int)HOLEoffsets.center_x], out double center_x); double.TryParse(shape[(int)HOLEoffsets.center_y], out double center_y); double.TryParse(shape[(int)HOLEoffsets.radius], out double radius); pcbComp.Add(new PcbArc { Layer = Layer.DrillDrawing, Location = CoordPoint.FromMils(LCSCcoordToMil(center_x - zero_x), 0 - LCSCcoordToMil(center_y - zero_y)), Radius = Coord.FromMils(LCSCcoordToMil(radius)), StartAngle = 0, EndAngle = 360 }); } else if (shape[0] == "TRACK") { double.TryParse(shape[(int)TRACKoffsets.stroke_width], out double stroke_width); pcbComp.Add(new PcbMetaTrack { Layer = LCSCLayerAltiumLayerMap[shape[(int)TRACKoffsets.layer_id]], Vertices = TrackPointsToListXY(shape[(int)TRACKoffsets.points], zero_x, zero_y), Width = Coord.FromMils(stroke_width) }); } else if (shape[0] == "RECT") { double.TryParse(shape[(int)RECToffsets.x], out double x); double.TryParse(shape[(int)RECToffsets.y], out double y); double.TryParse(shape[(int)RECToffsets.width], out double width); double.TryParse(shape[(int)RECToffsets.height], out double height); double.TryParse(shape[(int)RECToffsets.stroke_width], out double stroke_width); pcbComp.Add(new PcbMetaTrack { Layer = LCSCLayerAltiumLayerMap[shape[(int)RECToffsets.layer_id]], Vertices = new List <CoordPoint>() { CoordPoint.FromMils((Coord)LCSCcoordToMil(x - zero_x), 0 - (Coord)LCSCcoordToMil(y - zero_y)), CoordPoint.FromMils((Coord)LCSCcoordToMil(x - zero_x + width), 0 - (Coord)LCSCcoordToMil(y - zero_y)), CoordPoint.FromMils((Coord)LCSCcoordToMil(x - zero_x + width), 0 - (Coord)LCSCcoordToMil(y - zero_y + height)), CoordPoint.FromMils((Coord)LCSCcoordToMil(x - zero_x), 0 - (Coord)LCSCcoordToMil(y - zero_y + height)), CoordPoint.FromMils((Coord)LCSCcoordToMil(x - zero_x), 0 - (Coord)LCSCcoordToMil(y - zero_y)) }, Width = Coord.FromMils(stroke_width) }); } else if (shape[0] == "SOLIDREGION") { double.TryParse(shape[(int)SOLIDREGIONoffsets.points], out double width); SVGCommand.TryParse(shape[(int)SOLIDREGIONoffsets.points], out List <SVGCommand> points); List <CoordPoint> Outline = new List <CoordPoint>(); for (int i = 0; i < points.Count; i++) { switch (points[i].CMD) { case 'M': if (points[i].ARG.Length < 2) { throw new Exception("M svg path cmd should have 2 args"); } Outline.Add(CoordPoint.FromMils( (Coord)LCSCcoordToMil(points[i].ARG[0] - zero_x), 0 - (Coord)LCSCcoordToMil(points[i].ARG[1] - zero_y))); break; case 'L': if (points[i].ARG.Length < 2) { throw new Exception("L svg path cmd should have 2 args"); } Outline.Add(CoordPoint.FromMils( (Coord)LCSCcoordToMil(points[i].ARG[0] - zero_x), 0 - (Coord)LCSCcoordToMil(points[i].ARG[1] - zero_y))); break; default: throw new Exception("not expected svg path cmd"); } } pcbComp.Add(new PcbRegion { Layer = LCSCLayerAltiumLayerMap[shape[(int)SOLIDREGIONoffsets.layer_id]], Outline = Outline, IsKeepOut = shape[(int)SOLIDREGIONoffsets.type] == "cutout" }); } } pcbComp.Description = component.title; pcbComp.ItemGuid = component.uuid; pcbComp.RevisionGuid = component.uuid; return(pcbComp); }