Skip to content

Commit

Permalink
Allow to edit placements - fixes #38
Browse files Browse the repository at this point in the history
  • Loading branch information
yorikvanhavre committed Apr 12, 2023
1 parent 7f1fa48 commit 2ccac19
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 16 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Check for updates on this project at https://yorik.uncreated.net/blog/nativeifc

#### 4. Allow advanced editing

* [x] Allow to edit placements
* [ ] Define a strategy for expanding non-IfcProduct elements
* [ ] Expand attributes
* [ ] Expand materials
Expand Down
22 changes: 20 additions & 2 deletions ifc_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class ifc_object:
def __init__(self):

self.cached = True # this marks that the object is freshly created and its shape should be taken from cache

self.virgin_placement = True # this allows to set the initial placement without triggering any placement change

def onBeforeChange(self, obj, prop):

Expand Down Expand Up @@ -56,6 +56,14 @@ def onChanged(self, obj, prop):
elif prop == "Label":
self.edit_attribute(obj, "Name", obj.Label)

# change placement
if prop == "Placement":
if getattr(self,"virgin_placement",False):
self.virgin_placement = False
else:
# print("placement changed for",obj.Label,"to",obj.Placement)
self.edit_placement(obj)


def onDocumentRestored(self, obj):

Expand All @@ -66,7 +74,6 @@ def onDocumentRestored(self, obj):
if child.ShapeMode == "Coin":
child.Proxy.cached = True
child.touch()
obj.Document.recompute()


def rebuild_classlist(self, obj, setprops=False):
Expand Down Expand Up @@ -145,3 +152,14 @@ def set_schema(self, obj, schema):
if len(child) == 1:
child[0].StepId = new_id


def edit_placement(self, obj):

"""Syncs the internal IFC placement"""

import ifc_tools # lazy import

result = ifc_tools.set_placement(obj)
if result:
proj = ifc_tools.get_project(obj)
proj.Modified = True
1 change: 1 addition & 0 deletions ifc_selftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ def test09_CreateBIMObjects(self):
print(ifco, "IFC objects created")
self.failUnless(fco == 8 and ifco == 12, "CreateDocument failed")

# test changing placement
# test remove object


33 changes: 19 additions & 14 deletions ifc_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,18 +533,18 @@ def get_coin(elements, ifcfile, cached=False):
elements = rest
elements = [e for e in elements if has_representation(e)]
if not elements:
return nodes, None
return nodes, None, None
if nodes.getNumChildren():
print("DEBUG: The following elements are excluded because they make coin crash (need to investigate):")
print("DEBUG: If you wish to test, comment out line 488 (return nodes, None) in ifc_tools.py")
[print(" ", e) for e in elements]
return nodes, None
return nodes, None, None
progressbar = Base.ProgressIndicator()
total = len(elements)
progressbar.start("Generating "+str(total)+" shapes...",total)
iterator = get_geom_iterator(ifcfile, elements, brep=False)
if iterator is None:
return None, None
return None, None, None
while True:
item = iterator.get()
if item:
Expand All @@ -562,7 +562,8 @@ def get_coin(elements, ifcfile, cached=False):
matrix = get_freecad_matrix(item.transformation.matrix.data)
verts = item.geometry.verts
verts = [FreeCAD.Vector(verts[i:i+3]) for i in range(0,len(verts),3)]
verts = [tuple(matrix.multVec(v.multiply(SCALE))) for v in verts]
#verts = [tuple(matrix.multVec(v.multiply(SCALE))) for v in verts]
verts = [tuple(v.multiply(SCALE)) for v in verts]
coords = coin.SoCoordinate3()
coords.point.setValues(verts)
node.addChild(coords)
Expand All @@ -579,7 +580,7 @@ def get_coin(elements, ifcfile, cached=False):
break
set_cache(ifcfile, cache)
progressbar.stop()
return nodes, None
return nodes, None, FreeCAD.Placement(matrix)


def get_settings(ifcfile, brep=True):
Expand Down Expand Up @@ -658,8 +659,9 @@ def set_geometry(obj, elem, ifcfile, cached=False):
# case above. TODO do this more elegantly
obj.Shape = Part.makeBox(1,1,1)
# set coin representation
node, colors = get_coin([elem], ifcfile, cached)
node, colors, placement = get_coin([elem], ifcfile, cached)
basenode.addChild(node)
obj.Placement = placement
set_colors(obj, colors)


Expand Down Expand Up @@ -757,10 +759,11 @@ def get_ios_matrix(freecad_placement):
#pos = pos.multiply(1/SCALE) # does not work??
pos = FreeCAD.Vector(round(pos.x,4),round(pos.y,4),round(pos.z,4))
rot = freecad_placement.Rotation.multVec(FreeCAD.Vector(1,1,1))
mat = ( (rot.x, 0.0, 0.0, pos.x),
(0.0, rot.y, 0.0, pos.y),
(0.0, 0.0, rot.z, pos.z),
(0.0, 0.0, 0.0, 1.0 ) )
rot = FreeCAD.Vector(round(rot.x,8),round(rot.y,8),round(rot.z,8))
mat = [ [rot.x, 0.0, 0.0, pos.x],
[0.0, rot.y, 0.0, pos.y],
[0.0, 0.0, rot.z, pos.z],
[0.0, 0.0, 0.0, 1.0 ] ]
return mat


Expand All @@ -775,13 +778,15 @@ def set_placement(obj):
new_matrix = get_ios_matrix(obj.Placement)
old_matrix = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement)
# conversion from numpy array
old_matrix = tuple([tuple(p) for p in old_matrix.tolist()])
old_matrix = old_matrix.tolist()
if new_matrix != old_matrix:
print("DEBUG: placement changed for:",obj.Label)
print("old:",old_matrix)
print("new:",new_matrix)
# print("DEBUG: placement changed for:",obj.Label)
# print("old:",old_matrix)
# print("new:",new_matrix)
api = "geometry.edit_object_placement"
ifcopenshell.api.run(api, ifcfile, product=element, matrix=new_matrix, is_si=False)
return True
return False


def save_ifc(obj, filepath=None):
Expand Down

0 comments on commit 2ccac19

Please sign in to comment.