Skip to content

Commit

Permalink
allow BSplineSurfaces to be used as planes
Browse files Browse the repository at this point in the history
  • Loading branch information
kbwbe committed Apr 14, 2019
1 parent 37e67e7 commit 24d48eb
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 20 deletions.
2 changes: 1 addition & 1 deletion InitGui.py
Expand Up @@ -26,7 +26,7 @@
__title__ = 'A2plus assembly Workbench - InitGui file'
__author__ = 'kbwbe'

A2P_VERSION = 'V0.4.15'
A2P_VERSION = 'V0.4.16'



Expand Down
22 changes: 13 additions & 9 deletions a2p_constraints.py
Expand Up @@ -223,7 +223,7 @@ def calcInitialValues(self):
c = self.constraintObject
point = getPos(self.ob1, c.SubElement1)
plane = getObjectFaceFromName(self.ob2, c.SubElement2)
planeNormal = plane.Surface.Axis
planeNormal = a2plib.getPlaneNormal(plane.Surface)
planePos = getPos(self.ob2, c.SubElement2)
#
# calculate recent offset...
Expand Down Expand Up @@ -463,8 +463,10 @@ def calcInitialValues(self):
c = self.constraintObject
plane1 = getObjectFaceFromName(self.ob1, c.SubElement1)
plane2 = getObjectFaceFromName(self.ob2, c.SubElement2)
normal1 = plane1.Surface.Axis
normal2 = plane2.Surface.Axis

normal1 = a2plib.getPlaneNormal(plane1.Surface)
normal2 = a2plib.getPlaneNormal(plane2.Surface)

angle = math.degrees(normal1.getAngle(normal2))
if angle <= 90.0:
self.direction = "aligned"
Expand Down Expand Up @@ -513,8 +515,10 @@ def calcInitialValues(self):
c = self.constraintObject
plane1 = getObjectFaceFromName(self.ob1, c.SubElement1)
plane2 = getObjectFaceFromName(self.ob2, c.SubElement2)
normal1 = plane1.Surface.Axis
normal2 = plane2.Surface.Axis

normal1 = a2plib.getPlaneNormal(plane1.Surface)
normal2 = a2plib.getPlaneNormal(plane2.Surface)

angle = math.degrees(normal1.getAngle(normal2))
if angle <= 90.0:
self.direction = "aligned"
Expand Down Expand Up @@ -561,8 +565,8 @@ def __init__(self,selection):
def calcInitialValues(self):
plane1 = getObjectFaceFromName(self.ob1, self.sub1)
plane2 = getObjectFaceFromName(self.ob2, self.sub2)
normal1 = plane1.Surface.Axis
normal2 = plane2.Surface.Axis
normal1 = a2plib.getPlaneNormal(plane1.Surface)
normal2 = a2plib.getPlaneNormal(plane2.Surface)
self.angle = math.degrees(normal2.getAngle(normal1))

@staticmethod
Expand Down Expand Up @@ -661,8 +665,8 @@ def calcInitialValues(self):
#plane2 = getObjectFaceFromName(self.ob2, self.sub2)
CoM1 = plane1.CenterOfMass
CoM2 = plane2.CenterOfMass
axis1 = plane1.Surface.Axis
axis2 = plane2.Surface.Axis
axis1 = a2plib.getPlaneNormal(plane1.Surface)
axis2 = a2plib.getPlaneNormal(plane2.Surface)
angle = math.degrees(axis1.getAngle(axis2))
if angle <= 90.0:
self.direction = "aligned"
Expand Down
25 changes: 15 additions & 10 deletions a2p_dependencies.py
Expand Up @@ -192,7 +192,7 @@ def Create(doc, constraint, solver, rigid1, rigid2):
plane2 = getObjectFaceFromName(ob2, c.SubElement2)
dep2.refPoint = plane2.Faces[0].BoundBox.Center

normal2 = plane2.Surface.Axis
normal2 = a2plib.getPlaneNormal(plane2.Surface)
#shift refPoint of plane by offset
try:
offs = c.offset
Expand Down Expand Up @@ -239,8 +239,9 @@ def Create(doc, constraint, solver, rigid1, rigid2):
dep1.refPoint = plane1.Faces[0].BoundBox.Center
dep2.refPoint = plane2.Faces[0].BoundBox.Center

normal1 = plane1.Surface.Axis
normal2 = plane2.Surface.Axis
normal1 = a2plib.getPlaneNormal(plane1.Surface)
normal2 = a2plib.getPlaneNormal(plane2.Surface)

if dep2.direction == "opposed":
normal2.multiply(-1.0)
dep1.refAxisEnd = dep1.refPoint.add(normal1)
Expand All @@ -257,8 +258,8 @@ def Create(doc, constraint, solver, rigid1, rigid2):
dep1.refPoint = plane1.Faces[0].BoundBox.Center
dep2.refPoint = plane2.Faces[0].BoundBox.Center

normal1 = plane1.Surface.Axis
normal2 = plane2.Surface.Axis
normal1 = a2plib.getPlaneNormal(plane1.Surface)
normal2 = a2plib.getPlaneNormal(plane2.Surface)
dep1.refAxisEnd = dep1.refPoint.add(normal1)
dep2.refAxisEnd = dep2.refPoint.add(normal2)

Expand All @@ -273,8 +274,8 @@ def Create(doc, constraint, solver, rigid1, rigid2):
dep1.refPoint = plane1.Faces[0].BoundBox.Center
dep2.refPoint = plane2.Faces[0].BoundBox.Center

normal1 = plane1.Surface.Axis
normal2 = plane2.Surface.Axis
normal1 = a2plib.getPlaneNormal(plane1.Surface)
normal2 = a2plib.getPlaneNormal(plane2.Surface)
if dep2.direction == "opposed":
normal2.multiply(-1.0)
dep1.refAxisEnd = dep1.refPoint.add(normal1)
Expand Down Expand Up @@ -336,7 +337,7 @@ def Create(doc, constraint, solver, rigid1, rigid2):
axis1Normalized.normalize()
dep1.refAxisEnd = dep1.refPoint.add(axis1Normalized)

normal2 = plane2.Surface.Axis
normal2 = a2plib.getPlaneNormal(plane2.Surface)
dep2.refAxisEnd = dep2.refPoint.add(normal2)

elif c.Type == "CenterOfMass":
Expand All @@ -362,8 +363,12 @@ def Create(doc, constraint, solver, rigid1, rigid2):
#plane2 = getObjectFaceFromName(ob2, c.SubElement2)
# dep1.refPoint = plane1.Faces[0].CenterOfMass
# dep2.refPoint = plane2.Faces[0].CenterOfMass
normal1 = plane1.Surface.Axis
normal2 = plane2.Surface.Axis

#normal1 = plane1.Surface.Axis
#normal2 = plane2.Surface.Axis
normal1 = a2plib.getPlaneNormal(plane1.Surface)
normal2 = a2plib.getPlaneNormal(plane2.Surface)

if dep2.direction == "opposed":
normal2.multiply(-1.0)
dep1.refAxisEnd = dep1.refPoint.add(normal1)
Expand Down
32 changes: 32 additions & 0 deletions a2plib.py
Expand Up @@ -32,6 +32,8 @@
import sys
import copy
import platform
import numpy

from a2p_viewProviderProxies import *

PYVERSION = sys.version_info[0]
Expand Down Expand Up @@ -271,6 +273,19 @@ def appVersionStr():
subVersion = int(float(FreeCAD.Version()[1]))
return "%03d.%03d" %(version,subVersion)
#------------------------------------------------------------------------------
def numpyVecToFC(nv):
assert len(nv) == 3
return Base.Vector(nv[0],nv[1],nv[2])
#------------------------------------------------------------------------------
def fit_plane_to_surface1( surface, n_u=3, n_v=3 ):
uv = sum( [ [ (u,v) for u in numpy.linspace(0,1,n_u)] for v in numpy.linspace(0,1,n_v) ], [] )
P = [ surface.value(u,v) for u,v in uv ] #positions at u,v points
N = [ numpy.cross( *surface.tangent(u,v) ) for u,v in uv ]
plane_norm = sum(N) / len(N) #plane's normal, averaging done to reduce error
plane_pos = P[0]
error = sum([ abs( numpy.dot(p - plane_pos, plane_norm) ) for p in P ])
return numpyVecToFC(plane_norm), numpyVecToFC(plane_pos), error
#------------------------------------------------------------------------------
def isLine(param):
if hasattr(Part,"LineSegment"):
return isinstance(param,(Part.Line,Part.LineSegment))
Expand Down Expand Up @@ -604,6 +619,10 @@ def planeSelected( selection ):
face = getObjectFaceFromName( selection.Object, subElement)
if str(face.Surface) == '<Plane object>':
return True
elif str(face.Surface) == '<BSplineSurface object>':
normal,pos,error = fit_plane_to_surface1(face.Surface)
if abs(error) < 1e-9:
return True
return False
#------------------------------------------------------------------------------
def vertexSelected( selection ):
Expand Down Expand Up @@ -668,6 +687,8 @@ def getPos(obj, subElementName):
pos = surface.Center
elif str(surface).startswith('<SurfaceOfRevolution'):
pos = getObjectFaceFromName(obj, subElementName).Edges[0].Curve.Center
elif str(surface).startswith('<BSplineSurface'):
axis,pos,error = fit_plane_to_surface1(surface)
elif subElementName.startswith('Edge'):
edge = getObjectEdgeFromName(obj, subElementName)
if isLine(edge.Curve):
Expand All @@ -681,6 +702,14 @@ def getPos(obj, subElementName):
return getObjectVertexFromName(obj, subElementName).Point
return pos # maybe none !!
#------------------------------------------------------------------------------
def getPlaneNormal(surface):
axis = None
if hasattr(surface,'Axis'):
axis = surface.Axis
elif str(surface).startswith('<BSplineSurface'):
axis,pos,error = fit_plane_to_surface1(surface)
return axis # may be none!
#------------------------------------------------------------------------------
def getAxis(obj, subElementName):
axis = None
if subElementName.startswith('Face'):
Expand All @@ -690,6 +719,9 @@ def getAxis(obj, subElementName):
axis = surface.Axis
elif str(surface).startswith('<SurfaceOfRevolution'):
axis = face.Edges[0].Curve.Axis
elif str(surface).startswith('<BSplineSurface'):
axis,pos,error = fit_plane_to_surface1(surface)

elif subElementName.startswith('Edge'):
edge = getObjectEdgeFromName(obj, subElementName)
if isLine(edge.Curve):
Expand Down

0 comments on commit 24d48eb

Please sign in to comment.