[Discussion] A different approach to Arch modelling (Arch Assembly?)
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
Re: [Discussion] A different approach to Arch modelling (Arch Assembly?)
So this would not no longer use Sketch like currently ArchWindow does to generate shape right ?
Re: [Discussion] A different approach to Arch modelling (Arch Assembly?)
Code: Select all
"""
FreeCAD script - macro
to be used with the OnePartLib part library
copyright 2019 Carlo Dormeletti (onekk)
carlo.dormeletti@yahoo.com
Version:
"""
import sys
import datetime
import time
import importlib
import FreeCAD
import FreeCADGui
from FreeCAD import Rotation, Vector
import Part
import Draft
#import Mesh
#import MeshPart
# BEGIN DOC Settings
DEBUG = True
DBG_LOAD = False
DOC_NAME = "finestra"
# END DOC settings
#from math import pi cos, sin, pi, sqrt
import numpy as np
def activate_doc():
"""activate document"""
FreeCAD.setActiveDocument(DOC_NAME)
FreeCAD.ActiveDocument = FreeCAD.getDocument(DOC_NAME)
FreeCADGui.ActiveDocument = FreeCADGui.getDocument(DOC_NAME)
if DBG_LOAD is True:
print("{0} activated".format(DOC_NAME))
def setview():
"""Rearrange View"""
DOC.recompute()
VIEW.viewAxometric()
VIEW.setAxisCross(True)
VIEW.fitAll()
def clear_doc():
"""Clear the active document deleting all the objects"""
for obj in DOC.Objects:
DOC.removeObject(obj.Name)
if FreeCAD.ActiveDocument is None:
FreeCAD.newDocument(DOC_NAME)
if DBG_LOAD is True:
print("Document: {0} Created".format(DOC_NAME))
# test if there is an active document with a "proper" name
if FreeCAD.ActiveDocument.Name == DOC_NAME:
if DBG_LOAD is True:
print("DOC_NAME exist")
else:
if DBG_LOAD is True:
print("DOC_NAME is not active")
# test if there is a document with a "proper" name
try:
FreeCAD.getDocument(DOC_NAME)
except NameError:
if DBG_LOAD is True:
print("No Document: {0}".format(DOC_NAME))
FreeCAD.newDocument(DOC_NAME)
if DBG_LOAD is True:
print("Document {0} Created".format(DOC_NAME))
DOC = FreeCAD.getDocument(DOC_NAME)
GUI = FreeCADGui.getDocument(DOC_NAME)
VIEW = GUI.ActiveView
if DBG_LOAD is True:
print("DOC : {0} GUI : {1}".format(DOC, GUI))
activate_doc()
if DBG_LOAD is True:
print(FreeCAD.ActiveDocument.Name)
clear_doc()
EPS = 0.002
VZOR = Vector(0, 0, 0)
ROT0 = Rotation(0, 0, 0)
ROTX90 = Rotation(0, 0, 90)
ROTXN90 = Rotation(0, 0, -90)
ROTY90 = Rotation(0, 90, 0)
ROTZ180 = Rotation(180, 0, 0)
#Used to shorten most Placements
PL0 = FreeCAD.Placement(VZOR, ROT0)
# DOCUMENT START HERE
fin_h = 1400
fin_w = 1200
fin_th = 50
cont_w = 50
vetro_th = 3
vetro_add = 5
def telaio():
e_tel_w = fin_w
e_tel_h = fin_h
i_tel_w = fin_w - cont_w * 2
i_tel_h = fin_h - cont_w * 2
v_w = i_tel_w + vetro_add * 2
v_h = i_tel_h + vetro_add * 2
ep0 = (e_tel_w * -0.5, 0, 0)
ep1 = (e_tel_w * 0.5, 0, 0)
ep2 = (e_tel_w * 0.5, 0, e_tel_h)
ep3 = (e_tel_w * -0.5, 0, e_tel_h)
ip0 = (i_tel_w * -0.5, 0, cont_w)
ip1 = (i_tel_w * 0.5, 0, cont_w)
ip2 = (i_tel_w * 0.5, 0, cont_w + i_tel_h)
ip3 = (i_tel_w * -0.5, 0, cont_w + i_tel_h)
vp0 = (v_w * -0.5, 0, cont_w - vetro_add)
vp1 = (v_w * 0.5, 0, cont_w - vetro_add)
vp2 = (v_w * 0.5, 0, cont_w - vetro_add + v_h)
vp3 = (v_w * -0.5, 0, cont_w - vetro_add + v_h)
tel_b = (ep0, ep1, ip1, ip0, ep0)
tel_bp = Part.makePolygon([Vector(*vtx) for vtx in tel_b])
tel_r = (ep1, ep2, ip2, ip1, ep1)
tel_rp = Part.makePolygon([Vector(*vtx) for vtx in tel_r])
tel_t = (ep2, ep3, ip3, ip2, ep2)
tel_tp = Part.makePolygon([Vector(*vtx) for vtx in tel_t])
tel_l = (ep3, ep0, ip0, ip3, ep3)
tel_lp = Part.makePolygon([Vector(*vtx) for vtx in tel_l])
tel_fb = Part.makeFilledFace(tel_bp.Edges)
tel_fbs = tel_fb.extrude(Vector(0, fin_th, 0))
tel_fr = Part.makeFilledFace(tel_rp.Edges)
tel_frs = tel_fr.extrude(Vector(0, fin_th, 0))
tel_ft = Part.makeFilledFace(tel_tp.Edges)
tel_fts = tel_ft.extrude(Vector(0, fin_th, 0))
tel_fl = Part.makeFilledFace(tel_lp.Edges)
tel_fls = tel_fl.extrude(Vector(0, fin_th, 0))
vetro_pt = (vp0, vp1, vp2, vp3, vp0)
vetro_p = Part.makePolygon([Vector(*vtx) for vtx in vetro_pt])
vetro_f = Part.makeFilledFace(vetro_p.Edges)
vetro_s = vetro_f.extrude(Vector(0, vetro_th, 0))
vetro_s.Placement = FreeCAD.Placement(Vector(0, (fin_th - vetro_th) * 0.5, 0), ROT0)
obj0 = DOC.addObject("Part::Feature", "telaio")
obj0.Shape = Part.makeCompound((tel_fbs, tel_frs, tel_fts, tel_fls))
obj0.ViewObject.ShapeColor = (0.54, 0.27, 0.07) # rgb(139, 69, 19)
obj1 = DOC.addObject("Part::Feature", "vetro")
obj1.Shape = vetro_s
obj1.ViewObject.ShapeColor = (0.33, 0.67, 1.00)
obj1.ViewObject.Transparency = 50
obj_f = DOC.addObject("Part::Compound", "finestra")
obj_f.Links = [obj0, obj1]
return obj_f
telaio()
If you use my code, the axes are shown you will see that the window is created with the bottom center around Vector(0,0,0) and the window "extruding" by Y axes positive, seems to be a viable reference point, it lacks of the offset in y for the placement on the wall thickness and the sill dimensions (width length and thickness) to calculate the protrusion
#paulee no this is generating directly the shapes, draft object are returned as Part.Shapes with some additional properties.
Regards
Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.
Blog: https://okkmkblog.wordpress.com/
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.
Blog: https://okkmkblog.wordpress.com/
Re: [Discussion] A different approach to Arch modelling (Arch Assembly?)
Nice! The compound is a good approach, but I'd like the default window shape to be completely embedded into the opening object (so we spare several objects in the final count). Basically it's the Opening object that makes the final compound grouping the window and the sill (https://github.com/yorikvanhavre/BIM_Wo ... ing.py#L47).
The "get_window_shape" should be called right here: https://github.com/yorikvanhavre/BIM_Wo ... ng.py#L187
Hmm, I need the Placement.Base of the window in this red point:If you use my code, the axes are shown you will see that the window is created with the bottom center around Vector(0,0,0) and the window "extruding" by Y axes positive, seems to be a viable reference point, it lacks of the offset in y for the placement on the wall thickness and the sill dimensions (width length and thickness) to calculate the protrusion
@paullee, this is just a prototype for some default windows. Do not worry, I do not intend to loose the generation by sketch, but its slightly more complicated, so will come after
follow my experiments on BIM modelling for architecture design
Re: [Discussion] A different approach to Arch modelling (Arch Assembly?)
carlopav wrote: ↑Sun Jun 07, 2020 5:32 pmHmm, I need the Placement.Base of the window in this red point:If you use my code, the axes are shown you will see that the window is created with the bottom center around Vector(0,0,0) and the window "extruding" by Y axes positive, seems to be a viable reference point, it lacks of the offset in y for the placement on the wall thickness and the sill dimensions (width length and thickness) to calculate the protrusion
Cattura.JPG
This is the reference point, the center bottom of the frame, with the window extending in the z direction of an amount equal to opening_height
@paullee, this is just a prototype for some default windows. Do not worry, I do not intend to loose the generation by sketch, but its slightly more complicated, so will come after
The compound is retaining the colors, if I don't remember well if i fuse the object i will loose the colors and the ability to color the different faces, it is treated as a unique solid.
Let me see some more work, on the make the frame is only the external frame, now the opening part could be generated, 50mm for the frame and 50 mm for the opening simply "nested boxes" to reatin the seam each side has to be generated as a trapezoid.
More to come.
Regards
Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.
Blog: https://okkmkblog.wordpress.com/
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.
Blog: https://okkmkblog.wordpress.com/
Re: [Discussion] A different approach to Arch modelling (Arch Assembly?)
great, have fun!
follow my experiments on BIM modelling for architecture design
Re: [Discussion] A different approach to Arch modelling (Arch Assembly?)
Code: Select all
"""
FreeCAD script - macro
to be used with the OnePartLib part library
copyright 2019 Carlo Dormeletti (onekk)
carlo.dormeletti@yahoo.com
Version:
"""
import sys
import datetime
import time
import FreeCAD
import FreeCADGui
from FreeCAD import Rotation, Vector
import Part
import Draft
#import Mesh
#import MeshPart
# BEGIN DOC Settings
DEBUG = True
DBG_LOAD = False
DOC_NAME = "finestra"
# END DOC settings
#from math import pi cos, sin, pi, sqrt
import numpy as np
def activate_doc():
"""activate document"""
FreeCAD.setActiveDocument(DOC_NAME)
FreeCAD.ActiveDocument = FreeCAD.getDocument(DOC_NAME)
FreeCADGui.ActiveDocument = FreeCADGui.getDocument(DOC_NAME)
if DBG_LOAD is True:
print("{0} activated".format(DOC_NAME))
def setview():
"""Rearrange View"""
DOC.recompute()
VIEW.viewAxometric()
VIEW.setAxisCross(True)
VIEW.fitAll()
def clear_doc():
"""Clear the active document deleting all the objects"""
for obj in DOC.Objects:
DOC.removeObject(obj.Name)
if FreeCAD.ActiveDocument is None:
FreeCAD.newDocument(DOC_NAME)
if DBG_LOAD is True:
print("Document: {0} Created".format(DOC_NAME))
# test if there is an active document with a "proper" name
if FreeCAD.ActiveDocument.Name == DOC_NAME:
if DBG_LOAD is True:
print("DOC_NAME exist")
else:
if DBG_LOAD is True:
print("DOC_NAME is not active")
# test if there is a document with a "proper" name
try:
FreeCAD.getDocument(DOC_NAME)
except NameError:
if DBG_LOAD is True:
print("No Document: {0}".format(DOC_NAME))
FreeCAD.newDocument(DOC_NAME)
if DBG_LOAD is True:
print("Document {0} Created".format(DOC_NAME))
DOC = FreeCAD.getDocument(DOC_NAME)
GUI = FreeCADGui.getDocument(DOC_NAME)
VIEW = GUI.ActiveView
if DBG_LOAD is True:
print("DOC : {0} GUI : {1}".format(DOC, GUI))
activate_doc()
if DBG_LOAD is True:
print(FreeCAD.ActiveDocument.Name)
clear_doc()
EPS = 0.002
VZOR = Vector(0, 0, 0)
ROT0 = Rotation(0, 0, 0)
ROTX90 = Rotation(0, 0, 90)
ROTXN90 = Rotation(0, 0, -90)
ROTY90 = Rotation(0, 90, 0)
ROTZ180 = Rotation(180, 0, 0)
#Used to shorten most Placements
PL0 = FreeCAD.Placement(VZOR, ROT0)
# DOCUMENT START HERE
def telaio(tel_name, tel_w, tel_h , tel_ww, tel_wh, tel_th, et=0):
i_tel_w = tel_w - tel_ww * 2
i_tel_h = tel_h - tel_wh * 2
if et == 0:
ofz = 0
else:
ofz = tel_wh
ep0 = (tel_w * -0.5, 0, ofz)
ep1 = (tel_w * 0.5, 0, ofz)
ep2 = (tel_w * 0.5, 0, tel_h + ofz)
ep3 = (tel_w * -0.5, 0, tel_h + ofz)
ip0 = (i_tel_w * -0.5, 0, tel_ww + ofz)
ip1 = (i_tel_w * 0.5, 0, tel_ww + ofz)
ip2 = (i_tel_w * 0.5, 0, tel_ww + i_tel_h + ofz)
ip3 = (i_tel_w * -0.5, 0, tel_ww + i_tel_h + ofz)
tel_b = (ep0, ep1, ip1, ip0, ep0)
tel_bp = Part.makePolygon([Vector(*vtx) for vtx in tel_b])
tel_r = (ep1, ep2, ip2, ip1, ep1)
tel_rp = Part.makePolygon([Vector(*vtx) for vtx in tel_r])
tel_t = (ep2, ep3, ip3, ip2, ep2)
tel_tp = Part.makePolygon([Vector(*vtx) for vtx in tel_t])
tel_l = (ep3, ep0, ip0, ip3, ep3)
tel_lp = Part.makePolygon([Vector(*vtx) for vtx in tel_l])
tel_fb = Part.makeFilledFace(tel_bp.Edges)
tel_fbs = tel_fb.extrude(Vector(0, tel_th, 0))
tel_fr = Part.makeFilledFace(tel_rp.Edges)
tel_frs = tel_fr.extrude(Vector(0, tel_th, 0))
tel_ft = Part.makeFilledFace(tel_tp.Edges)
tel_fts = tel_ft.extrude(Vector(0, tel_th, 0))
tel_fl = Part.makeFilledFace(tel_lp.Edges)
tel_fls = tel_fl.extrude(Vector(0, tel_th, 0))
obj0 = DOC.addObject("Part::Feature", tel_name)
obj0.Shape = Part.makeCompound((tel_fbs, tel_frs, tel_fts, tel_fls))
obj0.ViewObject.ShapeColor = (0.54, 0.27, 0.07) # rgb(139, 69, 19)
return obj0
def finestra(opening_th=300, opening_height=1400, opening_width=1200,
frame_width=50, frame_th=50, glass_th=21):
vetro_add = 5
# permit to differentiate from the top-bottom
# and left right
frame_height = frame_width
cont_w = frame_width * 2
cont_h = frame_height * 2
ea_w = opening_width - cont_w
ea_h = opening_height - cont_h
v_w = ea_w - cont_w + vetro_add * 2
v_h = ea_h - cont_h + vetro_add * 2
vp0 = (v_w * -0.5, 0, cont_w - vetro_add)
vp1 = (v_w * 0.5, 0, cont_w - vetro_add)
vp2 = (v_w * 0.5, 0, cont_h - vetro_add + v_h)
vp3 = (v_w * -0.5, 0, cont_h - vetro_add + v_h)
vetro_pt = (vp0, vp1, vp2, vp3, vp0)
vetro_p = Part.makePolygon([Vector(*vtx) for vtx in vetro_pt])
vetro_f = Part.makeFilledFace(vetro_p.Edges)
vetro_s = vetro_f.extrude(Vector(0, glass_th, 0))
vetro_s.Placement = FreeCAD.Placement(Vector(0, (frame_th - glass_th) * 0.5, 0), ROT0)
obj_t = telaio("telaio", opening_width, opening_height, frame_width,
frame_height, frame_th, 0)
obj_ea = telaio("elemento apribile", ea_w, ea_h, frame_width,
frame_height, frame_th, 1)
obj1 = DOC.addObject("Part::Feature", "vetro")
obj1.Shape = vetro_s
obj1.ViewObject.ShapeColor = (0.33, 0.67, 1.00)
obj1.ViewObject.Transparency = 50
obj_f = DOC.addObject("Part::Compound", "finestra")
obj_f.Links = [obj_t, obj_ea, obj1]
return obj_f
finestra()
setview()
As I'have no opening object i have chosen to make all the dimensions explicit, there is provision for a different horizontal frame_height differentiate from the vertical elements
The frame is created byu the same routine, adding an offset value, of frame_height (the heigh of horizontal element).
I hope this combine flexibility and speed, as I have not used primitives, but created objects individually i hope the speed will be not a problem, as only the final elements are created as docObjects.
From my point of view the only things that lacks is the offset Y (the distance from the outer side of the wall to "position" the window).
Just ion case we could add some other things, like the glass stopper, but i think that it will be an unuseful addition.
Maybe we could define one or two "open element" half of the width of the resulting frame.
What do you think
Regards
Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.
Blog: https://okkmkblog.wordpress.com/
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.
Blog: https://okkmkblog.wordpress.com/
Re: [Discussion] A different approach to Arch modelling (Arch Assembly?)
I think that this is cool!
I like that you created a frame object that we can use multiple times inside the window! (edit: i stressed it a bit ad it seems quite fast!)
I modified it slightly to make it return a shape instead of creating a document object.
For the colors I have to check how Draft_Clone does it. But I think that it could be feasible also grouping everything inside just one shape.
The prototype is inside BIM workbench experimental tools since ... NOW!
We could think about different presets... for example we could define how many panes the window should have (1-2-3-10?)
I like that you created a frame object that we can use multiple times inside the window! (edit: i stressed it a bit ad it seems quite fast!)
I modified it slightly to make it return a shape instead of creating a document object.
In my idea this will be handled by the Opening object. (I already setted up the properties FillingAlignment and FillingDisplacement, I still miss the logic, but won't be difficult to implement).From my point of view the only things that lacks is the offset Y (the distance from the outer side of the wall to "position" the window).
For the colors I have to check how Draft_Clone does it. But I think that it could be feasible also grouping everything inside just one shape.
The prototype is inside BIM workbench experimental tools since ... NOW!
We could think about different presets... for example we could define how many panes the window should have (1-2-3-10?)
follow my experiments on BIM modelling for architecture design
Re: [Discussion] A different approach to Arch modelling (Arch Assembly?)
Thanks
Not to reinvent the wheel, if i reuse my code and add a number of panes in :
Code: Select all
def finestra(opening_th=300, opening_height=1400, opening_width=1200,
frame_width=50, frame_th=50, glass_th=21, n_pan=1):
For the sill, it have to be under the "opening" so the sill is flush with the opening partially overlap it and protrude slighlty outwards.
I could do some coding.
But lateral and top sills like is usually seen in some region of Italy (and also in Europe), or maybe we are doing too much.
Regards
Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.
Blog: https://okkmkblog.wordpress.com/
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.
Blog: https://okkmkblog.wordpress.com/
Re: [Discussion] A different approach to Arch modelling (Arch Assembly?)
Great!
For the sill, it should not overlap with the opening but with the wall, so if we have 100x150cm opening, after adding the sill the measures are still ok.
I was thinking about adding a Bool flag "subtract also positive shapes from the wall", so we can easily manage to have sills and windows overlapping with the wall, or bigger than the opening itself, as it often is in the reality.
Having the whole stone frame of the opening should be considered as well as the standard bottom sill, they can be 2 different options perhaps!
What do you think?
For the sill, it should not overlap with the opening but with the wall, so if we have 100x150cm opening, after adding the sill the measures are still ok.
I was thinking about adding a Bool flag "subtract also positive shapes from the wall", so we can easily manage to have sills and windows overlapping with the wall, or bigger than the opening itself, as it often is in the reality.
Having the whole stone frame of the opening should be considered as well as the standard bottom sill, they can be 2 different options perhaps!
What do you think?
follow my experiments on BIM modelling for architecture design