From 984cb42b1c6a4397d49f25dd431dbb2c5c23900a Mon Sep 17 00:00:00 2001 From: "Morgan 'ARR\\!' Allen" Date: Fri, 16 May 2025 22:43:39 -0700 Subject: [PATCH] wip towards SketchObjectPython feature for board outline This is helpful for preventing "sketch has been touhed after recompute type errors, which seem to occur because the sketch has been computed before the Board, which was doing the Sketch updates. --- freecad/kiconnect/board.py | 65 ++++---------------------- freecad/kiconnect/board_sketch.py | 77 +++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 57 deletions(-) create mode 100644 freecad/kiconnect/board_sketch.py diff --git a/freecad/kiconnect/board.py b/freecad/kiconnect/board.py index f686e4a..f6e1d89 100644 --- a/freecad/kiconnect/board.py +++ b/freecad/kiconnect/board.py @@ -11,6 +11,7 @@ from kipy.util.board_layer import BoardLayer from .bases import BaseObject, BaseViewProvider from . import parts as Parts +from . import board_sketch as BoardSketch class BoardObject(BaseObject): TYPE = 'KiConnect::Board' @@ -30,36 +31,17 @@ class BoardObject(BaseObject): self.feature.PolygonId = board_polygon.id.value + self.board_sketch = BoardSketch.makeBoardSketch(self.substrate_body, kicad_board, board_polygon) + self.create_substrate_pad() + @property def board_polygon(self): return [ poly for poly in extract_polygons(self.kicad_board) if poly.id.value == self.polygon_id ][0] - def execute(self, feature): - begin = None - start = None - - sketch = self.substrate_sketch - - # this probably needs a bit more control.. - sketch.Constraints = [] - sketch.Geometry = [] - - for vector in self.feature.Vectors: - if not start: - start = vector - begin = vector - - continue - - sketch.addGeometry(Part.LineSegment(start, vector)) - - start = vector - - sketch.addGeometry(Part.LineSegment(start, begin)) - def onDocumentRestored(self, feature): super(BoardObject, self).onDocumentRestored(feature) + self.board_sketch = self.feature.get('BoardSketch') self.kicad_board = self.get_api().kicad.get_board() @property @@ -71,15 +53,6 @@ class BoardObject(BaseObject): return body - @property - def substrate_sketch(self): - sketch = self.substrate_body.getObject('Sketch') - - if not sketch: - sketch = self.create_substrate_sketch() - - return sketch - def create_substrate_body(self): substrate_body = App.ActiveDocument.addObject('PartDesign::Body', 'Substrate') @@ -90,34 +63,14 @@ class BoardObject(BaseObject): return substrate_body - def create_substrate_sketch(self): - substrate_sketch = App.ActiveDocument.addObject('Sketcher::SketchObject', 'Sketch') - substrate_sketch.Visibility = False - - self.substrate_body.addObject(substrate_sketch) - + def create_substrate_pad(self): pad = self.substrate_body.newObject('PartDesign::Pad', 'Outline') - pad.Profile = substrate_sketch + pad.Profile = self.board_sketch pad.Length = 1.6 pad.Midplane = True - return substrate_sketch - - def extrude_substrate(self, feature): - self.substrate_sketch = App.ActiveDocument.addObject('Sketcher::SketchObject', 'Sketch') - self.substrate_sketch.Visibility = False - - self.substrate_body = App.ActiveDocument.addObject('PartDesign::Body', 'Substrate') - self.feature.addObject(self.substrate_body) - - pad = self.substrate_body.newObject('PartDesign::Pad', 'Outline') - - pad.Profile = self.substrate_sketch - pad.Length = 1.6 - pad.Midplane = True - - self.substrate_body.addObject(self.substrate_sketch) + return self.board_sketch def get_boardpoly(self): # TODO remove in favor of extract_polygons class method @@ -187,8 +140,6 @@ class BoardObject(BaseObject): self.feature.Vectors = vectors - App.ActiveDocument.recompute() - def sync_to(self): board = self.kicad_board diff --git a/freecad/kiconnect/board_sketch.py b/freecad/kiconnect/board_sketch.py new file mode 100644 index 0000000..abc30d2 --- /dev/null +++ b/freecad/kiconnect/board_sketch.py @@ -0,0 +1,77 @@ +import os + +import FreeCAD as App +from . import settings +import Part + +from kipy.board_types import Footprint3DModel, BoardPolygon, BoardSegment, PadStackShape +from kipy.geometry import PolygonWithHoles, PolyLine, PolyLineNode, Vector2 +from kipy.proto.common.types import KiCadObjectType +from kipy.util.board_layer import BoardLayer + +from .bases import BaseObject, BaseViewProvider + +class BoardSketchObject(BaseObject): + TYPE = 'KiConnect::BoardSketch' + + def __init__(self, feature, kicad_board, board_polygon): + super(BoardSketchObject, self).__init__(feature) + + #feature.Visibility = False + + vectors = [] + + for node in board_polygon.polygons[0].outline: + vectors.append(self.point_to_vector(node.point)) + + self.feature.Vectors = vectors + + def execute(self, feature): + begin = None + start = None + + # this probably needs a bit more control.. + feature.Constraints = [] + feature.Geometry = [] + + for vector in self.feature.Vectors: + if not start: + start = vector + begin = vector + + continue + + feature.addGeometry(Part.LineSegment(start, vector)) + start = vector + + feature.addGeometry(Part.LineSegment(start, begin)) + + feature.recompute() + + def point_to_vector(self, point, offset=True): + return ( + App.Vector(point.x, + -point.y + )) / 1000000.0 - (self.feature.BoardOffset.Base if offset else 0) + + def setup_properties(self, feature): + super(BoardSketchObject, self).setup_properties(feature) + + feature.addProperty('App::PropertyPlacement', 'BoardOffset', 'KiConnect', 'Internal offset for zeroing out Footprint offset', hidden=True, read_only=True) + feature.addProperty('App::PropertyVectorList', 'Vectors', 'KiConnect', 'Internal offset for zeroing out Footprint offset', hidden=True) + + def __getstate__(self): + return None + +class BoardSketchViewProvider(BaseViewProvider): + TYPE = 'KiConnect::BoardSketch' + #ICON = 'board.svg' + +def makeBoardSketch(parent, kicad_board, polygon): + feature = App.ActiveDocument.addObject('Sketcher::SketchObjectPython', 'BoardSketch') + parent.addObject(feature) + + BoardSketchObject(feature, kicad_board, polygon) + BoardSketchViewProvider(feature.ViewObject) + + return feature