private void ReadPrimitives(BinaryReader reader) { BeginContext("ReadPrimitives"); Root = new SchPrimitive(); Root.Record = -1; var primitives = new List <SchPrimitive>(); while (reader.BaseStream.Position < reader.BaseStream.Length) { var primitiveStartPosition = reader.BaseStream.Position; var primitive = ReadRecord(reader, size => ReadAsciiRecord(reader, size), size => ReadPinRecord(reader, size)); primitive.SetRawData(ExtractStreamData(reader, primitiveStartPosition, reader.BaseStream.Position)); /* * if (Sheet == null) * { * // First primitive read must be the board Record31 * AssertValue(nameof(primitive), primitive.GetType().Name, typeof(SheetRecord).Name); * Sheet = (SheetRecord)primitive; * } */ primitives.Add(primitive); } AssignOwners(primitives); EndContext(); }
/// <summary> /// Instantiates a record according to its record type number. /// </summary> /// <param name="recordType">Integer representing the record type.</param> /// <returns>A new empty instance of a record primitive.</returns> private SchPrimitive CreateRecord(int recordType) { SchPrimitive record; switch (recordType) { case 1: record = new SchComponent(); break; case 2: record = new PinRecord(); break; case 3: record = new SymbolRecord(); break; case 4: record = new TextStringRecord(); break; case 5: record = new BezierRecord(); break; case 6: record = new PolylineRecord(); break; case 7: record = new PolygonRecord(); break; case 8: record = new EllipseRecord(); break; case 9: record = new PieChartRecord(); break; case 10: record = new RoundedRectangleRecord(); break; case 11: record = new EllipticalArcRecord(); break; case 12: record = new ArcRecord(); break; case 13: record = new LineRecord(); break; case 14: record = new RectangleRecord(); break; case 28: case 209: record = new TextFrameRecord(); break; case 30: record = new ImageRecord(); break; case 34: record = new Record34(); break; case 41: record = new Record41(); break; case 44: record = new Record44(); break; case 45: record = new Record45(); break; case 46: record = new Record46(); break; case 48: record = new Record48(); break; default: EmitWarning($"Record {recordType} not supported"); record = new SchPrimitive(); break; } return(record); }
protected static void WritePrimitive(BinaryWriter writer, SchPrimitive primitive, bool pinAsBinary, int ownerIndex, ref int index, ref int pinIndex, Dictionary <int, (int x, int y, int length)> pinsFrac,
/// <summary> /// Converts the components and their schematic symbols from a BxlSharp document /// to the equivalent AltiumSharp schematic library. /// <remarks> /// This ignores the components' footprints. /// </remarks> /// </summary> /// <param name="document">BxlSharp document to have their schematic library data converted</param> /// <param name="hideAllParameters"> /// Many BXL documents have by default <c>RefDes</c> and <c>Value</c> attributes marked as /// being visible. If this argument is <c>true</c> then the visibility is ignored when /// creating the respective AltiumSharp component schematic parameters.</param> /// <param name="overrideRectangleLineWidth"> /// Optional value to be used when creating the rectangles in the document, instead of the /// values provided in the BxlSharp document. /// </param> /// <returns></returns> public static SchLib ConvertSymbols(BxlDocument document, bool hideAllParameters = false, LineWidth?overrideRectangleLineWidth = null, bool convertOverlines = true) { var schlib = new SchLib(); foreach (var component in document.Components) { var schComponent = new SchComponent { LibReference = component.Name, Designator = { Text = $"{component.RefDesPrefix}?" } }; // Read the general parameters for the component foreach (var libitem in component.Data) { SchPrimitive schPrimitive = null; switch (libitem) { case LibAttribute libAttribute: schPrimitive = new SchParameter { Location = ConvertPoint(libAttribute.Origin), Name = libAttribute.Name, Text = libAttribute.Text, FontId = GetFontId(schlib, document, libAttribute.TextStyle), Justification = ConvertJustification(libAttribute.Justify), Orientation = ConvertRotatation(libAttribute.Rotate), IsMirrored = libAttribute.IsFlipped, IsHidden = true, }; if (libAttribute.Name?.Equals("DESCRIPTION", StringComparison.InvariantCultureIgnoreCase) == true) { schComponent.ComponentDescription = libAttribute.Text; } break; case LibWizard libWizard: schPrimitive = new SchParameter { Location = ConvertPoint(libWizard.Origin), Name = libWizard.VarName, Text = libWizard.VarData }; break; } if (schPrimitive != null) { schComponent.Add(schPrimitive); } } // needed for fetching some parameter values var footprint = document.GetFootprint(component.PatternName); // each component has a set of schematic symbols equivalent to AD display modes and part numbers, // so we group them by part number and then iterate over each part's display modes var attachedSymbolsByPartNum = component.AttachedSymbols.Where(s => !string.IsNullOrEmpty(s.SymbolName)) .GroupBy(s => s.PartNum); foreach (var group in attachedSymbolsByPartNum) { var partNum = group.Key; if (partNum > schComponent.PartCount) { schComponent.AddPart(); } var displayMode = 0; foreach (var attachedSymbol in group) { var symbol = document.GetSymbol(attachedSymbol.SymbolName); if (symbol == null) { continue; } if (displayMode >= schComponent.DisplayModeCount) { schComponent.AddDisplayMode(); } var ignored = new HashSet <LibItem>(); // detect rectangles first so the are drawn in the background for (int j = 0; j < symbol.Data.Count; ++j) { if (DetectRectangle(symbol.Data, j, out var rectangle)) { ignored.Add(symbol.Data[j]); ignored.Add(symbol.Data[j + 1]); ignored.Add(symbol.Data[j + 2]); ignored.Add(symbol.Data[j + 3]); j += 3; rectangle.LineWidth = overrideRectangleLineWidth ?? rectangle.LineWidth; schComponent.Add(rectangle); } } foreach (var libitem in symbol.Data.Where(li => !ignored.Contains(li))) { SchPrimitive schPrimitive = null; switch (libitem) { case LibLine libLine: schPrimitive = new SchLine { Location = ConvertPoint(libLine.Origin), Corner = ConvertPoint(libLine.EndPoint), LineWidth = ConvertWidth(libLine.Width) }; break; case LibPoly libPoly: schPrimitive = new SchPolyline { Vertices = ConvertPoints(libPoly.Points), LineWidth = ConvertWidth(libPoly.Width) }; break; case LibArc libArc: schPrimitive = new SchArc { Location = ConvertPoint(libArc.Origin), Radius = Coord.FromMils(libArc.Radius), StartAngle = libArc.StartAngle, EndAngle = libArc.StartAngle + libArc.SweepAngle, LineWidth = ConvertWidth(libArc.Width) }; break; case LibText libText: schPrimitive = new SchLabel { Location = ConvertPoint(libText.Origin), Text = libText.Text, FontId = GetFontId(schlib, document, libText.TextStyle), Justification = ConvertJustification(libText.Justify), Orientation = ConvertRotatation(libText.Rotate), IsMirrored = libText.IsFlipped, IsHidden = !libText.IsVisible, }; break; case LibPin libPin: schPrimitive = new SchPin { Location = ConvertPoint(libPin.Origin), Designator = libPin.Designator.Text, Name = ConvertPinName(libPin.Name.Text, convertOverlines), NameVisible = libPin.Name.IsVisible, Orientation = ConvertRotatation(libPin.Rotate), DesignatorVisible = libPin.Designator.IsVisible, PinLength = Coord.FromMils(libPin.PinLength) }; break; case LibAttribute libAttribute: if (schComponent.GetParameter(libAttribute.Name) != null) { break; } var parameterValue = libAttribute.Text; if (string.IsNullOrEmpty(parameterValue) && footprint != null) { // when the value is empty, and not present in the component, Ultimate Librarian // gets the parameter value from the fooprint when exporting to Altium parameterValue = footprint.GetAttribute(libAttribute.Name)?.Text; } if (string.IsNullOrEmpty(parameterValue)) { parameterValue = component.GetAttribute(libAttribute.Name)?.Text; } schPrimitive = new SchParameter { Location = ConvertPoint(libAttribute.Origin), Name = libAttribute.Name, Text = parameterValue ?? string.Empty, FontId = GetFontId(schlib, document, libAttribute.TextStyle), Justification = ConvertJustification(libAttribute.Justify), Orientation = ConvertRotatation(libAttribute.Rotate), IsMirrored = libAttribute.IsFlipped, IsHidden = hideAllParameters || !libAttribute.IsVisible, }; break; case LibWizard libWizard: if (schComponent.GetParameter(libWizard.VarName) != null) { break; } schPrimitive = new SchParameter { Location = ConvertPoint(libWizard.Origin), Name = libWizard.VarName, Text = libWizard.VarData }; break; case null: break; default: throw new ArgumentOutOfRangeException(nameof(libitem)); } if (schPrimitive != null) { schPrimitive.OwnerPartDisplayMode = displayMode; schComponent.Add(schPrimitive); } } displayMode++; } } schComponent.DisplayMode = 0; schComponent.CurrentPartId = 1; schlib.Add(schComponent); } return(schlib); }