Arch: Further work on Space object
This commit is contained in:
parent
a882476c25
commit
dcb2ebf2ec
|
@ -319,17 +319,27 @@ def getCutVolume(cutplane,shapes):
|
|||
import Part
|
||||
if not isinstance(shapes,list):
|
||||
shapes = [shapes]
|
||||
placement = FreeCAD.Placement(cutplane.Placement)
|
||||
# building boundbox
|
||||
bb = shapes[0].BoundBox
|
||||
for sh in shapes[1:]:
|
||||
bb.add(sh.BoundBox)
|
||||
bb.enlarge(1)
|
||||
# building cutplane space
|
||||
placement = None
|
||||
um = vm = wm = 0
|
||||
ax = placement.Rotation.multVec(FreeCAD.Vector(0,0,1))
|
||||
u = placement.Rotation.multVec(FreeCAD.Vector(1,0,0))
|
||||
v = placement.Rotation.multVec(FreeCAD.Vector(0,1,0))
|
||||
if not bb.isCutPlane(placement.Base,ax):
|
||||
try:
|
||||
if hasattr(cutplane,"Shape"):
|
||||
p = cutplane.Shape.copy().Faces[0]
|
||||
else:
|
||||
p = cutplane.copy().Faces[0]
|
||||
except:
|
||||
FreeCAD.Console.PrintMessage(str(translate("Arch","Invalid cutplane")))
|
||||
return None,None,None
|
||||
ce = p.CenterOfMass
|
||||
ax = p.normalAt(0,0)
|
||||
u = p.Vertexes[1].Point.sub(p.Vertexes[0].Point).normalize()
|
||||
v = u.cross(ax)
|
||||
if not bb.isCutPlane(ce,ax):
|
||||
FreeCAD.Console.PrintMessage(str(translate("Arch","No objects are cut by the plane")))
|
||||
return None,None,None
|
||||
else:
|
||||
|
@ -342,20 +352,23 @@ def getCutVolume(cutplane,shapes):
|
|||
FreeCAD.Vector(bb.XMax,bb.YMin,bb.ZMax),
|
||||
FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMax)]
|
||||
for c in corners:
|
||||
dv = c.sub(placement.Base)
|
||||
dv = c.sub(ce)
|
||||
um1 = DraftVecUtils.project(dv,u).Length
|
||||
um = max(um,um1)
|
||||
vm1 = DraftVecUtils.project(dv,v).Length
|
||||
vm = max(vm,vm1)
|
||||
wm1 = DraftVecUtils.project(dv,ax).Length
|
||||
wm = max(wm,wm1)
|
||||
p1 = FreeCAD.Vector(-um,vm,0)
|
||||
p2 = FreeCAD.Vector(um,vm,0)
|
||||
p3 = FreeCAD.Vector(um,-vm,0)
|
||||
p4 = FreeCAD.Vector(-um,-vm,0)
|
||||
vu = DraftVecUtils.scaleTo(u,um)
|
||||
vui = DraftVecUtils.neg(vu)
|
||||
vv = DraftVecUtils.scaleTo(v,vm)
|
||||
vvi = DraftVecUtils.neg(vv)
|
||||
p1 = ce.add(vu.add(vvi))
|
||||
p2 = ce.add(vu.add(vv))
|
||||
p3 = ce.add(vui.add(vv))
|
||||
p4 = ce.add(vui.add(vvi))
|
||||
cutface = Part.makePolygon([p1,p2,p3,p4,p1])
|
||||
cutface = Part.Face(cutface)
|
||||
cutface.Placement = placement
|
||||
cutnormal = DraftVecUtils.scaleTo(ax,wm)
|
||||
cutvolume = cutface.extrude(cutnormal)
|
||||
cutnormal = DraftVecUtils.neg(cutnormal)
|
||||
|
|
|
@ -26,7 +26,9 @@ from DraftTools import translate
|
|||
from PyQt4 import QtCore
|
||||
|
||||
def makeSpace(objects):
|
||||
"""makeSpace(objects): Creates a space objects from the given boundary objects"""
|
||||
"""makeSpace(objects): Creates a space object from the given objects. Objects can be one
|
||||
document object, in which case it becomes the base shape of the space object, or a list of
|
||||
selection objects as got from getSelectionEx(), or a list of tuples (object, subobjectname)"""
|
||||
if not objects:
|
||||
return
|
||||
if not isinstance(objects,list):
|
||||
|
@ -38,8 +40,13 @@ def makeSpace(objects):
|
|||
obj.Base = objects[0]
|
||||
objects[0].ViewObject.hide()
|
||||
else:
|
||||
obj.Objects = objects
|
||||
|
||||
obj.Proxy.addSubobjects(objects)
|
||||
|
||||
def addSpaceBoundary(space,subobjects):
|
||||
"""addSpaceBoundary(space,subobjects): adds the given subobjects to the given space"""
|
||||
import Draft
|
||||
if Draft.getType(space) == "Space":
|
||||
space.Proxy.addSubobjects(space,subobjects)
|
||||
|
||||
class _CommandSpace:
|
||||
"the Arch Space command definition"
|
||||
|
@ -69,7 +76,7 @@ class _Space(ArchComponent.Component):
|
|||
obj.Proxy = self
|
||||
obj.addProperty("App::PropertyLink","Base","Base",
|
||||
str(translate("Arch","A base shape defining this space")))
|
||||
obj.addProperty("App::PropertyLinkList","Objects","Base",
|
||||
obj.addProperty("App::PropertyLinkSubList","Boundaries","Base",
|
||||
str(translate("Arch","The objects that make the boundaries of this space object")))
|
||||
self.Type = "Space"
|
||||
|
||||
|
@ -77,8 +84,24 @@ class _Space(ArchComponent.Component):
|
|||
self.getShape(obj)
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
if prop in ["Objects","Base"]:
|
||||
print prop
|
||||
if prop in ["Boundaries","Base"]:
|
||||
self.getShape(obj)
|
||||
|
||||
def addSubobjects(self,obj,subobjects):
|
||||
"adds subobjects to this space"
|
||||
objs = []
|
||||
for o in subobjects:
|
||||
print o
|
||||
if isinstance(o,tuple) or isinstance(o,list):
|
||||
objs.append(tuple(o))
|
||||
else:
|
||||
for el in o.SubElementNames:
|
||||
if "Face" in el:
|
||||
print "adding ",el
|
||||
objs.append((o.Object,el))
|
||||
print "boundaries to add: ",objs
|
||||
obj.Boundaries = objs
|
||||
|
||||
def getShape(self,obj):
|
||||
"computes a shape"
|
||||
|
@ -86,55 +109,65 @@ class _Space(ArchComponent.Component):
|
|||
shape = None
|
||||
faces = []
|
||||
|
||||
print "starting compute"
|
||||
# 1: if we have a base shape, we use it
|
||||
|
||||
if obj.Base:
|
||||
if obj.Base.isDerivedFrom("Part::Feature"):
|
||||
if obj.Base.Shape.Solids:
|
||||
shape = obj.Base.Shape.Solids[0]
|
||||
shape = obj.Base.Shape.Solids[0].copy()
|
||||
|
||||
# 2: if not, add all bounding boxes of considered objects and build a first shape
|
||||
if shape:
|
||||
print "got shape from base object"
|
||||
bb = shape.BoundBox
|
||||
else:
|
||||
bb = None
|
||||
for obj in obj.Objects:
|
||||
if obj.isDerivedFrom("Part::Feature"):
|
||||
for b in obj.Boundaries:
|
||||
if b[0].isDerivedFrom("Part::Feature"):
|
||||
if not bb:
|
||||
bb = obj.Shape.BoundBox
|
||||
bb = b[0].Shape.BoundBox
|
||||
else:
|
||||
bb.add(obj.Shape.BoundBox)
|
||||
bb.add(b[0].Shape.BoundBox)
|
||||
if not bb:
|
||||
return
|
||||
shape = Part.makeBox(bb.XLength,bb.YLength,bb.ZLength,FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMin))
|
||||
print "created shape from boundbox"
|
||||
|
||||
# 3: identify all faces pointing towards the center of our shape
|
||||
# 3: identifing boundary faces
|
||||
goodfaces = []
|
||||
for obj in obj.Objects:
|
||||
if obj.isDerivedFrom("Part::Feature"):
|
||||
faces.extend(obj.Shape.Faces)
|
||||
for face in faces:
|
||||
pt = face.CenterOfMass
|
||||
norm = face.normalAt(1,1) #TODO calculate for curved faces
|
||||
v1 = bb.Center.sub(pt)
|
||||
if v1.getAngle(norm) < math.pi/2:
|
||||
goodfaces.append(face)
|
||||
faces = goodfaces
|
||||
for b in obj.Boundaries:
|
||||
if b[0].isDerivedFrom("Part::Feature"):
|
||||
if "Face" in b[1]:
|
||||
fn = int(b[1][4:])-1
|
||||
faces.append(b[0].Shape.Faces[fn])
|
||||
print "adding face ",fn," of object ",b[0].Name
|
||||
|
||||
print "total: ", len(faces), " faces"
|
||||
|
||||
# 4: get cutvolumes from faces
|
||||
cutvolumes = []
|
||||
for f in faces:
|
||||
f = f.copy()
|
||||
f.reverse()
|
||||
cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(f,shape)
|
||||
if cutvolume:
|
||||
cutvolumes.append(cutvolume)
|
||||
print "generated 1 cutvolume"
|
||||
cutvolumes.append(cutvolume.copy())
|
||||
#Part.show(cutvolume)
|
||||
for v in cutvolumes:
|
||||
print "cutting"
|
||||
shape = shape.cut(v)
|
||||
|
||||
# 5: get the final shape
|
||||
if shape:
|
||||
if shape.Solids:
|
||||
print "setting objects shape"
|
||||
shape = shape.Solids[0]
|
||||
obj.Shape = shape
|
||||
return
|
||||
|
||||
print "something went wrong, bailing out"
|
||||
|
||||
|
||||
class _ViewProviderSpace(ArchComponent.ViewProviderComponent):
|
||||
|
|
Loading…
Reference in New Issue
Block a user