Skip to content

Commit

Permalink
improved support for push&pull bspline edges for kicad_pcb files
Browse files Browse the repository at this point in the history
  • Loading branch information
easyw committed May 10, 2019
1 parent f8bc1df commit d2fe3f1
Show file tree
Hide file tree
Showing 6 changed files with 833 additions and 90 deletions.
4 changes: 3 additions & 1 deletion changelog.txt
Expand Up @@ -7,7 +7,7 @@ maintained in the same accuracy and aspect in STEP AP214 format. +
The *kicad StepUp* maintains the usual way to work with kicad, but improves the process
to work in a collaborative way with mechanical designers bringing near ECAD and MCAD environments. +
With kicad StepUp you�ll get an exact representation of your physical board in Native 3D PCB
v8.3.0.3 April 2019
v8.3.1.0 May 2019

please refer to
kicadStepUp-starter-Guide.pdf
Expand Down Expand Up @@ -309,5 +309,7 @@ Changelog
- pushpcb working with gr_curves, downgrading to arcs and lines (TBD: use spline)
- spline w control points
- fixing pushpcb
- adding support for double quotes on kicad_pcb and kicad_mod format
- bsplines allowed for push&pull kicad_pcb
- most clean code and comments done

170 changes: 146 additions & 24 deletions constrainator.py
Expand Up @@ -3,20 +3,124 @@
#****************************************************************************

## todo :
# 1) add a dialog to set tolerance and constraint type
# 2) remove only coincident and hor-vert pre-existent constraints
# 3) add constraints only if not already present a coincident consstraint for that point
# 4) ATM only Line and Arcs are parsed
# ok 1) add a dialog to set tolerance and constraint type
# ok 2) remove only coincident and hor-vert pre-existent constraints
# ok 3) add constraints only if not already present a coincident constraint for that point
# ok 4) Line, Arcs, Bsplines, ArcOfEllipse are parsed
# 5) remove coindident bsplines (approx)

import FreeCAD, Part, Sketcher
from FreeCAD import Base
from math import sqrt

__ksuConstrainator_version__='1.1.5'
__ksuConstrainator_version__='1.1.6'

def sk_distance(p0, p1):
return sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2)
#

def sanitizeSkBsp(s_name, dist_tolerance):
# s_name = 'Sketch001'
s=FreeCAD.ActiveDocument.getObject(s_name)
FreeCAD.Console.PrintWarning('check to sanitize\n')
if 'Sketcher' in s.TypeId:
FreeCAD.ActiveDocument.openTransaction('Sanitizing')
idx_to_del = []
geo_to_del = []
inverted=False
# check for duplicates in splines
# NB!!! Knots are not reliable here to check!!!
if 1: #len (s.Geometry) > 2: #cleaning algo approx valid for more than 2 splines
for i,g in enumerate (s.Geometry):
if 'BSplineCurve object' in str(g):
j=i+1
for bg in s.Geometry[(i + 1):]:
if 'BSplineCurve object' in str(bg):
if j not in idx_to_del:
if (len(g.getPoles()) == len(bg.getPoles())):
#print('equal pole nbrs')
eqp = True
if sk_distance(g.StartPoint,bg.StartPoint) > dist_tolerance:
if sk_distance(g.StartPoint,bg.EndPoint) > dist_tolerance:
eqp = False
if sk_distance(g.EndPoint,bg.EndPoint) > dist_tolerance:
if sk_distance(g.EndPoint,bg.StartPoint) > dist_tolerance:
eqp = False
if (eqp):
if sk_distance(g.StartPoint,bg.StartPoint) > dist_tolerance:
inverted=True
else:
inverted=False
print ('identical splines, inverted=',inverted )
#print(g.getPoles())
#print(bg.getPoles())
if j not in idx_to_del:
print ('len ',len(bg.getPoles()))
if inverted == False:
for k,kn in enumerate (bg.getPoles()):
#a = float(kn); b = float(g.KnotSequence[k])
#print(k)
a = kn; b = g.getPole(k+1)
#print(kn,g.getPole(k+1))
#print('dif ',(float(kn)-float(g.KnotSequence[k])))
#print('abs ',abs(float(kn)-float(g.KnotSequence[k])))
#print(a,b)
#print(a[0],a[1],a[2])
#print(b[0],b[1],b[2])
#print('dif ',abs(a[0]-b[0]),abs(a[1]-b[1]),abs(a[2]-b[2]))
#print('abs ',abs(a-b))
#if abs(float(kn)-float(g.KnotSequence[k])) > dist_tolerance:
if abs(a[0]-b[0]) > dist_tolerance or abs(a[1]-b[1]) > dist_tolerance or abs(a[2]-b[2]) > dist_tolerance:
print('node NOT coincident')
#print(a,b)
eqp=False
break # break the for loop
#print('next--')
else:
l = len(bg.getPoles())
for k,kn in enumerate (bg.getPoles()):
#a = float(kn); b = float(g.KnotSequence[k])
#print(k)
a = kn; b = g.getPole(l-k)
#print(kn,g.getPole(l-k))
#print('dif ',(float(kn)-float(g.KnotSequence[k])))
#print('abs ',abs(float(kn)-float(g.KnotSequence[k])))
#print(a,b)
#print(a[0],a[1],a[2])
#print(b[0],b[1],b[2])
#print('dif ',abs(a[0]-b[0]),abs(a[1]-b[1]),abs(a[2]-b[2]))
#print('abs ',abs(a-b))
#if abs(float(kn)-float(g.KnotSequence[k])) > dist_tolerance:
if abs(a[0]-b[0]) > dist_tolerance or abs(a[1]-b[1]) > dist_tolerance or abs(a[2]-b[2]) > dist_tolerance:
print('node NOT coincident')
#print(a,b)
eqp=False
break # break the for loop
#print('next--')
if (eqp):
idx_to_del.append(j)
j+=1
j=0
#print(idx_to_del)
if len(idx_to_del) >0:
FreeCAD.Console.PrintMessage(u'sanitizing '+s.Label)
FreeCAD.Console.PrintMessage('\n')
idx_to_del.sort()
#print(idx_to_del)
idx_to_del.reverse()
#print(idx_to_del)
#stop
for i, e in enumerate(idx_to_del):
#print('to delete ',s.Geometry[(e)],e)
print('deleting identical geo')
#print(s.Geometry)
s.delGeometry(e)
#print(s.Geometry)
FreeCAD.ActiveDocument.commitTransaction()
return s.Geometry
else:
return None
##
def sanitizeSk(s_name, edg_tol):
''' simplifying & sanitizing sketches '''
#global edge_tolerance
Expand Down Expand Up @@ -58,6 +162,11 @@ def add_constraints(s_name, edge_tolerance, add_Constraints):
Part.Circle: [0, 3], # curve, center
Part.ArcOfCircle: [1, 2, 3], # first point, last point, center
Part.BSplineCurve: [0,1,2,3], # for poles
Part.ArcOfEllipse: [0,1,2,3], #
Part.Ellipse: [0,1], #
Part.ArcOfHyperbola: [0,1,2], #
Part.ArcOfParabola: [0,1,2], #
Part.Point: [0], #
}
else:
g_geom_points = {
Expand All @@ -66,32 +175,45 @@ def add_constraints(s_name, edge_tolerance, add_Constraints):
Part.Circle: [0, 3], # curve, center
Part.ArcOfCircle: [1, 2, 3], # first point, last point, center
Part.BSplineCurve: [0,1,2,3], # for poles
Part.ArcOfEllipse: [0,1,2,3], #
Part.Point: [0], #
}
points=[]
geoms=[]
#print len((s.Geometry))
#stop
for geom_index in range(len((s.Geometry))):
point_indexes = g_geom_points[type(s.Geometry[geom_index])]
#sayerr(point_indexes), say (geom_index)
#if 'Line' in type(PCB_Sketch.Geometry[geom_index]).__name__:

if 'ArcOfCircle' in type(s.Geometry[geom_index]).__name__\
or 'Line' in type(s.Geometry[geom_index]).__name__:
point1 = s.getPoint(geom_index, point_indexes[0])
#sayerr(str(point1[0])+';'+str(point1[1]))
point2 = s.getPoint(geom_index, point_indexes[1])
#sayw(str(point2[0])+';'+str(point1[1]))
#points.append([[point1[0],point1[1]],[geom_index],[1]])
#points.append([[point2[0],point2[1]],[geom_index],[2]])
#points.append([[point1[0],point1[1]],[geom_index]]) #,[1]])
#points.append([[point2[0],point2[1]],[geom_index]]) #,[2]])
if 'Line' in type(s.Geometry[geom_index]).__name__:
tp = 'Line'
else:
if not(s.Geometry[geom_index].Construction):
point_indexes = g_geom_points[type(s.Geometry[geom_index])]
#sayerr(point_indexes), say (geom_index)
#if 'Line' in type(PCB_Sketch.Geometry[geom_index]).__name__:

if 'ArcOfCircle' in type(s.Geometry[geom_index]).__name__\
or 'Line' in type(s.Geometry[geom_index]).__name__:
point1 = s.getPoint(geom_index, point_indexes[0])
#sayerr(str(point1[0])+';'+str(point1[1]))
point2 = s.getPoint(geom_index, point_indexes[1])
#sayw(str(point2[0])+';'+str(point1[1]))
#points.append([[point1[0],point1[1]],[geom_index],[1]])
#points.append([[point2[0],point2[1]],[geom_index],[2]])
#points.append([[point1[0],point1[1]],[geom_index]]) #,[1]])
#points.append([[point2[0],point2[1]],[geom_index]]) #,[2]])
if 'Line' in type(s.Geometry[geom_index]).__name__:
tp = 'Line'
else:
tp = 'Arc'
geoms.append([point1[0],point1[1],point2[0],point2[1],tp])
elif 'ArcOfEllipse' in type(s.Geometry[geom_index]).__name__\
or 'ArcOfHyperbola' in type(s.Geometry[geom_index]).__name__\
or 'ArcOfParabola' in type(s.Geometry[geom_index]).__name__:
point1 = s.getPoint(geom_index, point_indexes[1])
point2 = s.getPoint(geom_index, point_indexes[2])
tp = 'Arc'
geoms.append([point1[0],point1[1],point2[0],point2[1],tp])

geoms.append([point1[0],point1[1],point2[0],point2[1],tp])
elif 'Ellipse' in type(s.Geometry[geom_index]).__name__:
pass
elif 'Point' in type(s.Geometry[geom_index]).__name__:
pass
#
#print geom
sk_constraints = []
Expand Down

0 comments on commit d2fe3f1

Please sign in to comment.