Compare commits

..

No commits in common. "984cb42b1c6a4397d49f25dd431dbb2c5c23900a" and "c1194ecee097781f2bdca1efdd4a2925e43fa521" have entirely different histories.

6 changed files with 103 additions and 166 deletions

1
.gitignore vendored
View file

@ -1 +0,0 @@
__pycache__

View file

@ -11,8 +11,6 @@ class APIObject(BaseObject):
TYPE = 'KiConnect::API' TYPE = 'KiConnect::API'
def __init__(self, feature): def __init__(self, feature):
self.kicad = KiCad()
super(APIObject, self).__init__(feature) super(APIObject, self).__init__(feature)
feature.addProperty('App::PropertyFile', 'Socket', 'KiConnect', 'Path to the KiCAD Socket File').Socket = '/tmp/kicad/api.lock' feature.addProperty('App::PropertyFile', 'Socket', 'KiConnect', 'Path to the KiCAD Socket File').Socket = '/tmp/kicad/api.lock'
@ -21,8 +19,6 @@ class APIObject(BaseObject):
self.onDocumentRestored(feature) self.onDocumentRestored(feature)
self.ping_connection(feature)
def onDocumentRestored(self, feature): def onDocumentRestored(self, feature):
super(APIObject, self).onDocumentRestored(feature) super(APIObject, self).onDocumentRestored(feature)

View file

@ -12,8 +12,6 @@ class BaseObject:
feature.Type = self.TYPE feature.Type = self.TYPE
self.sync_from()
def execute(self, feature): def execute(self, feature):
# TODO this might not be the right move # TODO this might not be the right move
print(self, 'BaseObject.execute') print(self, 'BaseObject.execute')
@ -54,7 +52,7 @@ class BaseObject:
self.feature.addExtension(ext) self.feature.addExtension(ext)
def setup_properties(self, feature): def setup_properties(self, feature):
feature.addProperty('App::PropertyString', 'Type', 'KiConnect', 'Internal KiConnect Type', read_only=True, hidden=True) feature.addProperty('App::PropertyString', 'Type', 'KiConnect', 'Internatl KiConnect Type', read_only=True, hidden=True)
def sync_from(self): def sync_from(self):
pass pass

View file

@ -10,48 +10,45 @@ from kipy.proto.common.types import KiCadObjectType
from kipy.util.board_layer import BoardLayer from kipy.util.board_layer import BoardLayer
from .bases import BaseObject, BaseViewProvider from .bases import BaseObject, BaseViewProvider
from . import parts as Parts from . import parts
from . import board_sketch as BoardSketch
class BoardObject(BaseObject): class BoardObject(BaseObject):
TYPE = 'KiConnect::Board' TYPE = 'KiConnect::Board'
def __init__(self, feature, kicad_board, board_polygon): def __init__(self, feature):
self.feature = feature
self.kicad_board = kicad_board
# TODO add this to FreeCAD Preferences and Property?
self.do_offset = True
# TODO needs to be resotred in onDocumentRestored
#self.board_polygon = board_polygon
self.polygon_id = board_polygon.id.value
self.via_sketch = None
super(BoardObject, self).__init__(feature) super(BoardObject, self).__init__(feature)
self.feature.PolygonId = board_polygon.id.value self.kicad_board = None
self.via_sketch = None
self.board_sketch = BoardSketch.makeBoardSketch(self.substrate_body, kicad_board, board_polygon) feature.addProperty('App::PropertyPlacement', 'BoardOffset', 'KiConnect', 'Internal offset for zeroing out Footprint offset', hidden=True, read_only=True)
self.create_substrate_pad()
@property
def board_polygon(self): def execute(self, feature):
return [ poly for poly in extract_polygons(self.kicad_board) if poly.id.value == self.polygon_id ][0] super(BoardObject, self).execute(feature)
if self.kicad_board is None:
self.kicad_board = self.get_api().kicad.get_board()
if not self.substrate_body:
self.create_substrate_body()
if not self.substrate_sketch:
self.create_substrate_sketch()
self.sketch_outline()
def onDocumentRestored(self, feature): def onDocumentRestored(self, feature):
super(BoardObject, self).onDocumentRestored(feature) super(BoardObject, self).onDocumentRestored(feature)
self.board_sketch = self.feature.get('BoardSketch')
self.kicad_board = self.get_api().kicad.get_board() self.kicad_board = self.get_api().kicad.get_board()
@property @property
def substrate_body(self): def substrate_body(self):
body = self.feature.getObject('Substrate') return self.feature.getObject('Substrate')
if not body: @property
body = self.create_substrate_body() def substrate_sketch(self):
return self.substrate_body.getObject('Sketch')
return body
def create_substrate_body(self): def create_substrate_body(self):
substrate_body = App.ActiveDocument.addObject('PartDesign::Body', 'Substrate') substrate_body = App.ActiveDocument.addObject('PartDesign::Body', 'Substrate')
@ -61,19 +58,35 @@ class BoardObject(BaseObject):
self.feature.addObject(substrate_body) self.feature.addObject(substrate_body)
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 = self.substrate_body.newObject('PartDesign::Pad', 'Outline')
pad.Profile = self.board_sketch pad.Profile = substrate_sketch
pad.Length = 1.6 pad.Length = 1.6
pad.Midplane = True pad.Midplane = True
return self.board_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)
def get_boardpoly(self): def get_boardpoly(self):
# TODO remove in favor of extract_polygons class method
board = self.kicad_board board = self.kicad_board
# find polygons of Edge Cuts # find polygons of Edge Cuts
@ -116,29 +129,59 @@ class BoardObject(BaseObject):
via_pocket.Midplane = True via_pocket.Midplane = True
via_pocket.Type = 1 via_pocket.Type = 1
def point_to_vector(self, point, offset=True): def sketch_outline(self, do_offset=True):
return (
App.Vector(point.x,
-point.y
)) / 1000000.0 - (self.feature.BoardOffset.Base if offset else 0)
def sync_from(self):
''' '''
Pulls outline from KiCAD PolygonBoard and saves points as Vectors Draws the Board outline fetched from the API
Parameters:
do_offset (bool): If offset should be recalcualted, typically this is undesired after calculated the first time. (Default: True)
''' '''
# bit of a quick hack to keep the board in one place, needs more testing boardpoly = self.get_boardpoly()
if self.do_offset and not self.feature.BoardOffset: poly = boardpoly.polygons[0]
bb = self.board_polygon.bounding_box()
# track KIID
# TODO FeaturePython objects interacting with kipy objects should inherit common parent class
self.feature.PolygonId = boardpoly.id.value
# this offset centers the board to 0,0
if do_offset:
bb = boardpoly.bounding_box()
self.feature.BoardOffset.Base = (App.Vector(bb.pos.x, -bb.pos.y) + App.Vector(bb.size.x, -bb.size.y) / 2) / 1000000.0 self.feature.BoardOffset.Base = (App.Vector(bb.pos.x, -bb.pos.y) + App.Vector(bb.size.x, -bb.size.y) / 2) / 1000000.0
vectors = [] begin = None
start = None
# reset Sketch Constraints and Geometry
self.substrate_sketch.Constraints = []
self.substrate_sketch.Geometry = []
for node in self.board_polygon.polygons[0].outline: # sketch outline
vectors.append(self.point_to_vector(node.point)) for segment in poly.outline:
if not start:
start = (App.Vector(segment.point.x, -segment.point.y)) / 1000000.0 - self.feature.BoardOffset.Base
# needs to remain to connect the last segment
begin = start
self.feature.Vectors = vectors continue
end = (App.Vector(segment.point.x, -segment.point.y)) / 1000000.0 - self.feature.BoardOffset.Base
self.substrate_sketch.addGeometry(
Part.LineSegment(start, end)
)
start = end
# make final connection
self.substrate_sketch.addGeometry(
Part.LineSegment(start, begin)
)
def sync_from(self):
self.sketch_outline()
self.substrate_body.recompute(True)
def sync_to(self): def sync_to(self):
board = self.kicad_board board = self.kicad_board
@ -169,22 +212,6 @@ class BoardObject(BaseObject):
# maybe save the selection and restore if not empty, else select the poly as below # maybe save the selection and restore if not empty, else select the poly as below
#board.add_to_selection(boardpoly) #board.add_to_selection(boardpoly)
def setup_properties(self, feature):
super(BoardObject, self).setup_properties(feature)
kicad_board = self.kicad_board
feature.addProperty('App::PropertyPlacement', 'BoardOffset', 'KiConnect', 'Internal offset for zeroing out Footprint offset', hidden=True, read_only=True)
feature.addProperty('App::PropertyString', 'Doc', 'KiConnect', 'Doc in project to sync with', read_only=True)
feature.addProperty('App::PropertyString', 'PolygonId', 'KiConnect', 'Polygon ID for the original outline', hidden=True, read_only=True)
feature.addProperty('App::PropertyLength', 'Thickness', 'KiConnect', 'Thickness of PCB', hidden=True, read_only=True)
feature.addProperty('App::PropertyVectorList', 'Vectors', 'KiConnect', 'Internal offset for zeroing out Footprint offset', hidden=True)
feature.Doc = kicad_board.name
if not feature.Thickness:
feature.Thickness = 1.6
def __getstate__(self): def __getstate__(self):
return None return None
@ -192,22 +219,18 @@ class BoardViewProvider(BaseViewProvider):
TYPE = 'KiConnect::Board' TYPE = 'KiConnect::Board'
ICON = 'board.svg' ICON = 'board.svg'
def makeBoard(parent, kicad_board, polygon): class Board:
feature = App.ActiveDocument.addObject('App::DocumentObjectGroupPython', 'Board') def __init__(self, kicad_board, parent):
parent.addObject(feature) feature = App.ActiveDocument.addObject('App::DocumentObjectGroupPython', 'Board')
parent.addObject(feature)
self.feature = feature
BoardObject(feature, kicad_board, polygon) BoardObject(feature)
BoardViewProvider(feature.ViewObject) BoardViewProvider(feature.ViewObject)
Parts.makeParts(feature) # TODO move into BoardObject
feature.addProperty('App::PropertyString', 'Doc', 'KiConnect', 'Doc in project to sync with', read_only=True).Doc = kicad_board.name
feature.addProperty('App::PropertyString', 'PolygonId', 'KiConnect', 'Polygon ID for the original outline', hidden=True, read_only=True)
return feature parts.makeParts(feature)
def extract_polygons(board):
# find polygons of Edge Cuts
edge_cuts = [ edge for edge in board.get_shapes() if edge.layer == BoardLayer.BL_Edge_Cuts ]
polygons = [ edge for edge in edge_cuts if isinstance(edge, BoardPolygon) ]
# XXX only single board supported at the moment
return polygons

View file

@ -1,77 +0,0 @@
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

View file

@ -9,7 +9,7 @@ from . import settings
from . import api from . import api
from .copper import Copper from .copper import Copper
from . import board as Board from .board import Board
#from .parts import Parts #from .parts import Parts
class Project: class Project:
@ -31,9 +31,7 @@ class Project:
if self.API.Proxy.is_connected and self.API.DocumentCount > 0: if self.API.Proxy.is_connected and self.API.DocumentCount > 0:
kicad_board = self.API.Proxy.kicad.get_board() kicad_board = self.API.Proxy.kicad.get_board()
polygons = Board.extract_polygons(kicad_board) self.board = Board(kicad_board, self.feature)
for polygon in polygons:
self.board = Board.makeBoard(self.feature, kicad_board, polygon)
#self.copper = Copper(kicad_board, self.board) #self.copper = Copper(kicad_board, self.board)
#self.board.feature.addObject(self.copper.feature) #self.board.feature.addObject(self.copper.feature)