From c05d4bfb604c38e2373969a578eca057718b732b Mon Sep 17 00:00:00 2001 From: "U. Bruhin" Date: Sun, 23 Jun 2024 13:55:34 +0200 Subject: [PATCH] DO: Add 3D models --- generate_do.py | 86 +++++++++++++++++++++++++++++++++++++++++++++-- uuid_cache_do.csv | 8 +++++ 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/generate_do.py b/generate_do.py index e38d4d5..ba2bf54 100644 --- a/generate_do.py +++ b/generate_do.py @@ -4,6 +4,7 @@ - JEDEC DO-214 https://www.jedec.org/system/files/docs/DO-214D.PDF """ +import sys from os import path from uuid import uuid4 @@ -16,9 +17,9 @@ Layer, Name, Polygon, Position, Position3D, Rotation, Rotation3D, Value, Version, Vertex, Width ) from entities.package import ( - AssemblyType, AutoRotate, ComponentSide, CopperClearance, Footprint, FootprintPad, LetterSpacing, LineSpacing, - Mirror, Package, PackagePad, PackagePadUuid, PadFunction, Shape, ShapeRadius, Size, SolderPasteConfig, - StopMaskConfig, StrokeText, StrokeWidth + AssemblyType, AutoRotate, ComponentSide, CopperClearance, Footprint, Footprint3DModel, FootprintPad, LetterSpacing, + LineSpacing, Mirror, Package, Package3DModel, PackagePad, PackagePadUuid, PadFunction, Shape, ShapeRadius, Size, + SolderPasteConfig, StopMaskConfig, StrokeText, StrokeWidth ) GENERATOR_NAME = 'librepcb-parts-generator (generate_do.py)' @@ -76,6 +77,7 @@ def generate_pkg( author: str, config: DoConfig, polarity: bool, + generate_3d_models: bool, pkgcat: str, version: str, create_date: Optional[str], @@ -352,10 +354,86 @@ def _add_silkscreen( _add_footprint(package, Name('default'), 'default-') + # Generate 3D models + uuid_3d = _uuid('3d') + if generate_3d_models: + generate_3d(library, pkg_name, uuid_pkg, uuid_3d, config, polarity) + package.add_3d_model(Package3DModel(uuid_3d, Name(pkg_name))) + for footprint in package.footprints: + footprint.add_3d_model(Footprint3DModel(uuid_3d)) + package.serialize(path.join('out', library, 'pkg')) +def generate_3d( + library: str, + pkg_name: str, + uuid_pkg: str, + uuid_3d: str, + config: DoConfig, + polarity: bool, +) -> None: + import cadquery as cq + + from cadquery_helpers import StepAssembly, StepColor + + print(f'Generating pkg 3D model "{pkg_name}": {uuid_3d}') + + body_standoff = 0.15 + (0.05 + 0.3) / 2 # A2 + A3 + leg_height = (0.15 + 0.41) / 2 # c + leg_z_top = body_standoff + (config.body_height / 2) + (leg_height / 2) + bend_radius = 0.1 + (leg_height / 2) + body_chamfer_xy = 0.15 # rough estimation + body_chamfer_z = (config.body_height - leg_height) / 2 + bar_length = 0.2 * config.body_length + bar_width = config.body_width - (3 * body_chamfer_xy) + bar_height = 0.02 + bar_x = -(config.body_length - bar_length) / 2 + (2 * body_chamfer_xy) + + body = cq.Workplane('XY', origin=(0, 0, body_standoff + (config.body_height / 2))) \ + .box(config.body_length, config.body_width, config.body_height) \ + .edges('|Y').chamfer(body_chamfer_z, body_chamfer_xy) \ + .edges('|X').chamfer(body_chamfer_z, body_chamfer_xy) + bar = cq.Workplane('XY', origin=(bar_x, 0, body_standoff + config.body_height)) \ + .box(bar_length, bar_width, bar_height) + leg_path = cq.Workplane("XZ") \ + .hLine(-config.contact_length + (leg_height / 2) + bend_radius) \ + .ellipseArc(x_radius=bend_radius, y_radius=bend_radius, angle1=180, angle2=270, sense=-1) \ + .vLine(leg_z_top - leg_height - (2 * bend_radius)) \ + .ellipseArc(x_radius=bend_radius, y_radius=bend_radius, angle1=90, angle2=180, sense=-1) \ + .hLine(config.contact_length) + leg = cq.Workplane("ZY") \ + .rect(leg_height, config.contact_width) \ + .sweep(leg_path) + + assembly = StepAssembly(pkg_name) + assembly.add_body(body, 'body', StepColor.IC_BODY) + if polarity: + assembly.add_body(bar, 'bar', StepColor.IC_PIN1_DOT) + lead_x = (config.total_length / 2) - config.contact_length + assembly.add_body(leg, 'leg-1', StepColor.LEAD_SMT, + location=cq.Location((-lead_x, 0, leg_height / 2))) + assembly.add_body(leg, 'leg-2', StepColor.LEAD_SMT, + location=cq.Location((lead_x, 0, leg_height / 2), (0, 0, 1), 180)) + + # Save without fusing for slightly better minification. + out_path = path.join('out', library, 'pkg', uuid_pkg, f'{uuid_3d}.step') + assembly.save(out_path, fused=False) + + if __name__ == '__main__': + if '--help' in sys.argv or '-h' in sys.argv: + print(f'Usage: {sys.argv[0]} [--3d]') + print() + print('Options:') + print(' --3d Generate 3D models using cadquery') + sys.exit(1) + + generate_3d_models = '--3d' in sys.argv + if not generate_3d_models: + warning = 'Note: Not generating 3D models unless the "--3d" argument is passed in!' + print(f'\033[1;33m{warning}\033[0m') + configs = [] # body_length_nom (E1); body_width_nom (D); body_height_nom (A1) @@ -388,6 +466,7 @@ def _add_silkscreen( author='murray', config=config, polarity=True, + generate_3d_models=generate_3d_models, pkgcat='dcaa6b6c-0c55-43fd-a320-5dd74a2cdc85', version='0.1', create_date='2023-08-15T22:33:08Z', @@ -397,6 +476,7 @@ def _add_silkscreen( author='murray', config=config, polarity=False, + generate_3d_models=generate_3d_models, pkgcat='dcaa6b6c-0c55-43fd-a320-5dd74a2cdc85', version='0.1', create_date='2023-08-15T22:33:08Z', diff --git a/uuid_cache_do.csv b/uuid_cache_do.csv index 028b2a9..8fa7a31 100644 --- a/uuid_cache_do.csv +++ b/uuid_cache_do.csv @@ -1,3 +1,4 @@ +pkg-diom5226x240-3d,03f09b29-31af-4f37-a67e-86ffff65b00b pkg-diom5226x240-default-body,a98a77ba-852b-4f4f-9fb1-2d771cd6b00d pkg-diom5226x240-default-cathodeband,d2d47d2a-9d38-46b7-a238-4df579f193f2 pkg-diom5226x240-default-courtyard,5be08b28-4b26-4ac1-8aae-09307f077511 @@ -10,6 +11,7 @@ pkg-diom5226x240-default-text-value,2174a448-8b22-4072-8fb4-ad93ccba590d pkg-diom5226x240-pad-a,70bb734f-a4c2-49c2-871c-e5ae843dd50e pkg-diom5226x240-pad-c,fa650833-d0d0-4c48-b73a-bf6137341842 pkg-diom5226x240-pkg,09222d37-5ed9-4409-aa3d-2f6d78a4fdd8 +pkg-diom5226x295-3d,e5b1d3ae-5d12-4a59-9103-dd89763c485c pkg-diom5226x295-default-body,0bde6393-3a14-421d-b2c2-7f41cda9bb94 pkg-diom5226x295-default-cathodeband,cd25abf0-8d01-4c2e-a7d6-227816e8ffb5 pkg-diom5226x295-default-courtyard,bae933f3-644d-47a1-902c-214d31972ba8 @@ -22,6 +24,7 @@ pkg-diom5226x295-default-text-value,3661aa06-6df6-4c8a-81c1-e14e0fcf5d50 pkg-diom5226x295-pad-a,2dff4cbc-d050-4658-8f57-4b0ed0f9b876 pkg-diom5226x295-pad-c,d89f5209-c457-431e-bcfe-98296d8535b3 pkg-diom5226x295-pkg,f7380b5e-1cc4-46e3-94b9-dfa7e2785056 +pkg-diom5436x230-3d,3ca99c30-7f5f-4048-a51a-bf9a7710a00b pkg-diom5436x230-default-body,af9979e6-981d-4ac0-9e40-a596ffb460a6 pkg-diom5436x230-default-cathodeband,b00d514f-4304-48f4-a4b8-87550b94bc4e pkg-diom5436x230-default-courtyard,f4d4c0b4-dff1-4788-8f3a-bb07ed507336 @@ -34,6 +37,7 @@ pkg-diom5436x230-default-text-value,7d38931f-28be-48a7-af5d-9f53270c5007 pkg-diom5436x230-pad-a,b782f0d8-3175-4405-ad7d-28132b5d535a pkg-diom5436x230-pad-c,8be51409-30aa-42d6-98e4-fead8c6c400f pkg-diom5436x230-pkg,4cfa109d-bc5f-4268-8901-cc2a4349704d +pkg-diom7959x230-3d,1ab7bd40-ca78-4fde-8f0e-2ee718c17030 pkg-diom7959x230-default-body,9383bc4d-452d-4f76-a33a-5bbc9064189b pkg-diom7959x230-default-cathodeband,e8c93dd1-4e7d-41c9-8451-62d05fe8549e pkg-diom7959x230-default-courtyard,9dd926ae-6919-4180-bfa2-76d42d98b685 @@ -46,6 +50,7 @@ pkg-diom7959x230-default-text-value,4c785cb8-3275-434e-a0bd-23f5493e9f83 pkg-diom7959x230-pad-a,6170f57b-d9ef-4138-9747-12f56bd83427 pkg-diom7959x230-pad-c,66d018a3-81ba-4fb4-badc-8bbb0678e808 pkg-diom7959x230-pkg,4a0138a3-fa5f-4e17-8bd9-14a3d1817a98 +pkg-dionm5226x240-3d,0889a69a-5961-4e7e-9b29-3b52b1251efd pkg-dionm5226x240-default-body,e3dc664f-db86-480c-b979-774782e56c88 pkg-dionm5226x240-default-courtyard,845ef858-e22d-4e61-8229-c8770994c325 pkg-dionm5226x240-default-footprint,82bf40ff-a368-4577-bc71-8034bed3ca8b @@ -58,6 +63,7 @@ pkg-dionm5226x240-default-text-value,8413a6d8-f61f-4676-a516-213f9daf557a pkg-dionm5226x240-pad-1,22313f50-6c0b-4e17-960b-03a57c0bf6a6 pkg-dionm5226x240-pad-2,36983fd8-d9c6-47b1-8fa2-bb55268f7397 pkg-dionm5226x240-pkg,11a510a7-e928-4797-8a5a-4e66bc126c7c +pkg-dionm5226x295-3d,caf6cb8b-9cce-49e0-be47-5935210440dc pkg-dionm5226x295-default-body,8d9f8c9c-a29d-4453-9c80-434dd4097947 pkg-dionm5226x295-default-courtyard,b8e6f33e-8803-4d5f-b7c1-5aced330acdb pkg-dionm5226x295-default-footprint,bccdf787-faa0-4436-a96e-27a8665819a7 @@ -70,6 +76,7 @@ pkg-dionm5226x295-default-text-value,bb2f9eab-ca5a-4b92-bf49-709a5fa3203a pkg-dionm5226x295-pad-1,a2963994-0109-44b8-a1d9-13643aa1c986 pkg-dionm5226x295-pad-2,a21cd98c-6e8b-461f-a554-269b85cd6610 pkg-dionm5226x295-pkg,6cc5ff9c-4400-44ca-8671-870b490f8ab5 +pkg-dionm5436x230-3d,9150402b-3fec-4d15-bdc3-ebfd1ba39246 pkg-dionm5436x230-default-body,755ef9a7-775e-489b-9e33-7e30285e77c7 pkg-dionm5436x230-default-courtyard,6078faf8-4a7d-4a8e-ad8b-14ec8d752d40 pkg-dionm5436x230-default-footprint,14647a56-930d-402b-89ea-fac72e7a98b6 @@ -82,6 +89,7 @@ pkg-dionm5436x230-default-text-value,0010d2e1-7192-4901-864a-ee52c8cf6b04 pkg-dionm5436x230-pad-1,bce9702a-6106-4ebc-9ce0-0f1ce3a1b837 pkg-dionm5436x230-pad-2,d03a99a6-5ef9-4c0c-9ea4-c18397f0cb5a pkg-dionm5436x230-pkg,fc5f3f2b-8773-4069-9961-7c14a6674568 +pkg-dionm7959x230-3d,e4a00e81-50a1-4256-94e6-35719b68be53 pkg-dionm7959x230-default-body,746bb004-0e4b-4ee2-99ee-ef755fe2370a pkg-dionm7959x230-default-courtyard,a9531d97-7084-44b9-91a1-0e5ebf219e94 pkg-dionm7959x230-default-footprint,4f80d30d-9899-4208-96ed-69660c4d4c2b