/// <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); }
private static int GetFontId(SchLib schLib, BxlDocument document, string textStyle) { return(1); // always use the default font }