[Closed]Test Create ArchRebar2 Object

A forum dedicated to the Draft, Arch and BIM workbenches development.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
bernd
Veteran
Posts: 12849
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland
Contact:

Re: Test Create ArchRebar2 Object

Post by bernd »

@Yorik:
Do you know if there has ever been some afford to make an editor for the Property::Map?
User avatar
yorik
Founder
Posts: 13640
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: Test Create ArchRebar2 Object

Post by yorik »

bernd wrote:Do you know if there has ever been some afford to make an editor for the Property::Map?
No I don't think so...
User avatar
chakkree
Posts: 327
Joined: Tue Jun 30, 2015 12:58 am
Location: Bangkok Thailand

Re: Test Create ArchRebar2 Object

Post by chakkree »

ArchRebar2 --
New Concept -- Modified from ArchPipe
but Dwire can not dynamic change position(x,y,z) of points.
I make a new class that inherits from Draft._Wire. In DataView tab, you can change the value of A, B, and C.(distance of U-shape rebar)

Code: Select all

# -*- coding: utf8 -*-

#
#  Modified from ArchPipe
#*   Copyright (c) 2017                *
#*   chakkree tiyawongsuwan                              *

import FreeCAD, ArchComponent
import Draft



def makeRebar2(baseobj=None,diameter=0,length=0,placement=None,name="Rebar"):
    
    "makeRebar2([baseobj,diamerter,length,placement,name]): creates an Rebar object from the given base object"
    
    obj= FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
    obj.Label = name
    _Rebar2(obj)
    if FreeCAD.GuiUp:
        _ViewProviderRebar2(obj.ViewObject)
        if baseobj:
            baseobj.ViewObject.hide()
    if baseobj:
        obj.Base = baseobj
    else:
        if length:
            obj.Length = length
        else:
            obj.Length = 1000
    if diameter:
        obj.Diameter = diameter
    else:
        p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
        obj.Diameter = p.GetFloat("RebarDiameter",50)
    if placement:
        obj.Placement = placement
    return obj

class _Rebar2(ArchComponent.Component):
    
    
    def __init__(self,obj):

        ArchComponent.Component.__init__(self,obj)
        self.Type = "Rebar"
        obj.Role = ["ReinforcingBar"]
        obj.addProperty("App::PropertyLength", "Diameter",    "Arch", "The diameter of this pipe, if not based on a profile")
        obj.addProperty("App::PropertyLength", "Length",      "Arch", "The length of this pipe, if not based on an edge")
        obj.addProperty("App::PropertyLink",   "Profile",     "Arch", "An optional closed profile to base this pipe on")
        #obj.addProperty("App::PropertyLength", "OffsetStart", "Arch", QT_TRANSLATE_NOOP("App::Property","Offset from the start point"))
        #obj.addProperty("App::PropertyLength", "OffsetEnd",   "Arch", QT_TRANSLATE_NOOP("App::Property","Offset from the end point"))

    def execute(self,obj):
        
        import Part,DraftGeomUtils,math
        pl = obj.Placement
        w = self.getWire(obj)
        if not w:
            FreeCAD.Console.PrintError("Unable to build the base path\n")
            return
        """
        if obj.OffsetStart.Value:
            e = w.Edges[0]
            v = e.Vertexes[-1].Point.sub(e.Vertexes[0].Point).normalize()
            v.multiply(obj.OffsetStart.Value)
            e = Part.LineSegment(e.Vertexes[0].Point.add(v),e.Vertexes[-1].Point).toShape()
            w = Part.Wire([e]+w.Edges[1:])
        if obj.OffsetEnd.Value:
            e = w.Edges[-1]
            v = e.Vertexes[0].Point.sub(e.Vertexes[-1].Point).normalize()
            v.multiply(obj.OffsetEnd.Value)
            e = Part.LineSegment(e.Vertexes[-1].Point.add(v),e.Vertexes[0].Point).toShape()
            w = Part.Wire(w.Edges[:-1]+[e])
        """
        p = self.getProfile(obj)
        if not p:
            FreeCAD.Console.PrintError(translate("Arch","Unable to build the profile\n"))
            return
        # move and rotate the profile to the first point
        delta = w.Vertexes[0].Point-p.CenterOfMass
        p.translate(delta)
        v1 = w.Vertexes[1].Point-w.Vertexes[0].Point
        v2 = DraftGeomUtils.getNormal(p)
        rot = FreeCAD.Rotation(v2,v1)
        p.rotate(p.CenterOfMass,rot.Axis,math.degrees(rot.Angle))
        try:
            sh = w.makePipeShell([p],True,False,2)
        except:
            FreeCAD.Console.PrintError(translate("Arch","Unable to build the Rebar\n"))
        else:
            obj.Shape = sh
            if obj.Base:
                obj.Length = w.Length
            else:
                obj.Placement = pl
    
    def getWire(self,obj):
        
        import Part
        if obj.Base:
            if not obj.Base.isDerivedFrom("Part::Feature"):
                FreeCAD.Console.PrintError("The base object is not a Part\n")
                return
            if len(obj.Base.Shape.Wires) != 1:
                FreeCAD.Console.PrintError("Too many wires in the base shape\n")
                return
            if obj.Base.Shape.Wires[0].isClosed():
                FreeCAD.Console.PrintError("The base wire is closed\n")
                return
            w = obj.Base.Shape.Wires[0]
        else:
            if obj.Length.Value == 0:
                return
            w = Part.Wire([Part.LineSegment(FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,obj.Length.Value)).toShape()])
        return w
    
    def getProfile(self,obj):
        
        import Part
        if obj.Profile:
            if not obj.Profile.isDerivedFrom("Part::Part2DObject"):
                FreeCAD.Console.PrintError(translate("Arch","The profile is not a 2D Part\n"))
                return
            if len(obj.Profile.Shape.Wires) != 1:
                FreeCAD.Console.PrintError(translate("Arch","Too many wires in the profile\n"))
                return
            if not obj.Base.Profile.Wires[0].isClosed():
                FreeCAD.Console.PrintError(translate("Arch","The profile is not closed\n"))
                return
            p = obj.Base.Profile.Wires[0]
        else:
            if obj.Diameter.Value == 0:
                return
            p = Part.Wire([Part.Circle(FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1),obj.Diameter.Value/2).toShape()])
        return p


class _ViewProviderRebar2(ArchComponent.ViewProviderComponent):
    "A View Provider for the Pipe object"

    def __init__(self,vobj):

        ArchComponent.ViewProviderComponent.__init__(self,vobj)
        vobj.ShapeColor = (0.667,0.000,0.000)

    def getIcon(self):

        import Arch_rc
        return ":/icons/Arch_Rebar_Tree.svg"

class ShapeU(Draft._Wire):
    def __init__(self,obj):
        Draft._Wire.__init__(self,obj)
        obj.addProperty("App::PropertyLength", "A",    "Rebar", "The Length A of U-shape rebar")
        obj.addProperty("App::PropertyLength", "B",    "Rebar", "The Length B of U-shape rebar")
        obj.addProperty("App::PropertyLength", "C",    "Rebar", "The Length C of U-shape rebar")

    def execute(self,obj):
        pointslist=[
         FreeCAD.Vector(0,0,obj.A),
         FreeCAD.Vector(0,0,0),
         FreeCAD.Vector(obj.B,0,0),
         FreeCAD.Vector(obj.B,0,obj.C),
        ]
        obj.Points = pointslist
        obj.Closed = False
        obj.MakeFace = False
        obj.Support = None
        
        Draft._Wire.execute(self,obj)


class ShapeStirrup(Draft._Wire):
    def __init__(self,obj):
        Draft._Wire.__init__(self,obj)
        obj.addProperty("App::PropertyLength", "A",    "Rebar", "The Length A of U-shape rebar")
        obj.addProperty("App::PropertyLength", "B",    "Rebar", "The Length B of U-shape rebar")

    def execute(self,obj):
        pointslist=[
         FreeCAD.Vector(0,0,obj.A),
         FreeCAD.Vector(0,0,0),
         FreeCAD.Vector(obj.B,0,0),
         FreeCAD.Vector(obj.B,0,obj.C),
        ]
        obj.Points = pointslist
        obj.Closed = False
        obj.MakeFace = False
        obj.Support = None
        
        Draft._Wire.execute(self,obj)

        
if __name__=='__main__':
    """
    rebar1 = makeRebar2()

    points=[
     FreeCAD.Vector(150,0,191),
     FreeCAD.Vector(0,0,191),
     FreeCAD.Vector(0,0,0),
     FreeCAD.Vector(891,0,0),
     FreeCAD.Vector(891,0,191),
     FreeCAD.Vector(741,0,191),
    ]

    line = Draft.makeWire(points,closed=False,face=False,support=None)
    dia2 = 12
    line.FilletRadius = 2*dia2 + 0.5*dia2
    rebar2 = makeRebar2(line)
    """


    dia3 = 12
    name ='shapeU'
    line3= FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython",name)
    ShapeU(line3)
    Draft._ViewProviderWire(line3.ViewObject)
    line3.A = 300
    line3.B = 1000
    line3.C = 500

    line3.MakeFace = False
    line3.FilletRadius = 2*dia3 +0.5*dia3

    rebar3 = makeRebar2(line3)
    rebar3.Diameter = dia3
    rebar3.Placement.Base = FreeCAD.Vector(0 , 1000 , 0)

    FreeCAD.ActiveDocument.recompute()
Result form macro:
NewArchRebar2.png
NewArchRebar2.png (231.12 KiB) Viewed 1816 times
User avatar
chakkree
Posts: 327
Joined: Tue Jun 30, 2015 12:58 am
Location: Bangkok Thailand

Re: Test Create ArchRebar2 Object

Post by chakkree »

Create rebars using pivy.coin
- check save .iv flie
- check add to scenegraph

Next step: try to make Scripted obeject that contain pivy.coin code.

Code: Select all

#-*- coding=utf8 -*-
'''
  Test Create rebars by pivy.coin
'''

import os
from pivy import coin
from math import sin,cos ,pi

def creteRebarU(dia = 12, A= 300, B=1000 , num = 1 , spacing = 100):
    Switch = coin.SoSwitch()
    Switch.whichChild = 1
    
    Group1 = coin.SoGroup()
    Switch.addChild(Group1)
    
    myNode = coin.SoSeparator()
    Group1.addChild(myNode)
    myNode.setName('RebarU1')
    material = coin.SoMaterial()    
    material.diffuseColor.setValue(0.667, 0.000,0.000)
    material.specularColor.setValue(1,1,1)
    rebar = coin.SoVRMLExtrusion()
    rebar.beginCap = True
    rebar.endCap = True
    
    n = 3*4
    r = dia/2.0
    points = []
    for i in range(0,n+1):
        x = r * cos(2*pi/n*i); y = r * sin(2*pi/n*i)
        points.append( coin.SbVec2f(  x   ,  y) )
    crossSection = coin.SoMFVec2f()
    crossSection.setValues(points)    
    rebar.crossSection=crossSection
    
    R = 2.0*dia
    points = []
    points.append( coin.SbVec3f(  0   ,  -B/2 , A) )
    points.append( coin.SbVec3f(  0   ,  -B/2 , R) )
    n = 6
    for i in range(0,n):
        dx = R * cos(pi/2/n*i); dy = R * sin(pi/2/n*i)
        x = -B/2 + R-dx ;  y = +R-dy
        points.append( coin.SbVec3f(  0   ,  x , y) )
    points.append( coin.SbVec3f(  0   ,  -B/2+R , 0) )
    points.append( coin.SbVec3f(  0   ,  +B/2-R , 0) )
    for i in range(0,n):
        dx = R * cos(pi/2/n*i); dy = R * sin(pi/2/n*i)
        x = +B/2-R + dy ;  y = +R-dx
        points.append( coin.SbVec3f(  0   ,  x , y) )
    points.append( coin.SbVec3f(  0   ,  +B/2 , R) )
    points.append( coin.SbVec3f(  0   ,  +B/2 , A) )
    rebar.spine.setValues(points )
    
    myNode.addChild(material)
    myNode.addChild(rebar)
    
    Group2 = coin.SoGroup()
    Switch.addChild(Group2)
    
    tr = coin.SoTransform()
    tr.translation.setValue(0,0,0)
    tr.rotation.setValue(0,0,1 , 0.00   )
    Group2.addChild(tr)
    array1 = coin.SoArray() 
    Group2.addChild(array1)
    array1.origin = 'CENTER'
    array1.numElements1 = num
    array1.separation1.setValue(spacing,0,0)
    array1.addChild(myNode)
    
    return Switch

if __name__=='__main__':
    B = 1500; L = B
    t = 300
    numRebar = 10
    dia = 12
    '''
    B = 5000; L = B
    t = 800
    numRebar = 48
    dia = 19
    '''
    
    
    covering = 50
    R = 2*dia
    spacing1 = (B-2*covering - dia - 2*R)/float(numRebar-1)
    
    rebarA = t-2*covering - dia
    rebarB  = B-2*covering - dia
    rebarSet1 = creteRebarU(A= rebarA , B=rebarB ,dia = dia, num=numRebar , spacing = spacing1)
    rebarSet2 = creteRebarU(A= rebarA-dia , B=rebarB ,dia = dia, num=numRebar , spacing = spacing1)
    
    
    
    footingSep = coin.SoSeparator()
    group1 = rebarSet1.getChildren()[1]
    tr = group1.getChildren()[0]
    tr.translation.setValue(0,0,covering+dia/2.0)
    
    group2 = rebarSet2.getChildren()[1]
    tr = group2.getChildren()[0]
    tr.translation.setValue(0,0,dia)
    tr.rotation.setValue(coin.SbRotation(coin.SbVec3f(0.0, 0.0, 1.0), pi/2.0))
    
    material = coin.SoMaterial()
    material.transparency.setValue(0.55)
    material.diffuseColor.setValue(0.000,0.667,1.000)
    tr = coin.SoTransform()
    tr.translation.setValue(0,0,+t/2)
    
    concSep = coin.SoSeparator()
    concrete = coin.SoCube()
    concrete.width = L
    concrete.height=B
    concrete.depth = t
    concSep.addChild(material)
    concSep.addChild(tr)
    concSep.addChild(concrete)
    
    footingSep.addChild(concSep)
    footingSep.addChild(rebarSet1)
    footingSep.addChild(rebarSet2)
    
    
    sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph()
    sg.addChild(footingSep)
    
    filePath, fileName = os.path.split(__file__)
    out=coin.SoOutput()
    out.openFile(filePath+os.sep+'Rebar_U_temp.iv')
    wa = coin.SoWriteAction(out)
    wa.apply(footingSep)
    #wa.apply(rebarSet2)
    #wa.apply(concSep)
    out.closeFile()
    
    
    Msg('Done!!\n\n')
    
FootingRebar_pivycoin.png
FootingRebar_pivycoin.png (359.1 KiB) Viewed 1732 times
User avatar
chakkree
Posts: 327
Joined: Tue Jun 30, 2015 12:58 am
Location: Bangkok Thailand

Re: Test Create ArchRebar2 Object

Post by chakkree »

Test Parametric Structural Square footing.
using pivy.coin for a model.

Code: Select all

#-*- coding=utf8 -*-
"""
  StrucFooting.py
"""

import FreeCAD, FreeCADGui
from pivy import coin
from math import sin,cos ,pi

def creteRebarU(dia = 12, A= 300, B=1000 , num = 1 , spacing = 100):
    Switch = coin.SoSwitch()
    Switch.whichChild = 1
    
    Group1 = coin.SoGroup()
    Switch.addChild(Group1)
    
    myNode = coin.SoSeparator()
    Group1.addChild(myNode)
    myNode.setName('RebarU1')
    material = coin.SoMaterial()    
    material.diffuseColor.setValue(0.667, 0.000,0.000)
    material.specularColor.setValue(1,1,1)
    rebar = coin.SoVRMLExtrusion()
    rebar.beginCap = True
    rebar.endCap = True
    
    n = 3*4
    r = dia/2.0
    points = []
    for i in range(0,n+1):
        x = r * cos(2*pi/n*i); y = r * sin(2*pi/n*i)
        points.append( coin.SbVec2f(  x   ,  y) )
    crossSection = coin.SoMFVec2f()
    crossSection.setValues(points)    
    rebar.crossSection=crossSection
    
    R = 2.0*dia
    points = []
    points.append( coin.SbVec3f(  0   ,  -B/2 , A) )
    points.append( coin.SbVec3f(  0   ,  -B/2 , R) )
    n = 6
    for i in range(0,n):
        dx = R * cos(pi/2/n*i); dy = R * sin(pi/2/n*i)
        x = -B/2 + R-dx ;  y = +R-dy
        points.append( coin.SbVec3f(  0   ,  x , y) )
    points.append( coin.SbVec3f(  0   ,  -B/2+R , 0) )
    points.append( coin.SbVec3f(  0   ,  +B/2-R , 0) )
    for i in range(0,n):
        dx = R * cos(pi/2/n*i); dy = R * sin(pi/2/n*i)
        x = +B/2-R + dy ;  y = +R-dx
        points.append( coin.SbVec3f(  0   ,  x , y) )
    points.append( coin.SbVec3f(  0   ,  +B/2 , R) )
    points.append( coin.SbVec3f(  0   ,  +B/2 , A) )
    rebar.spine.setValues(points )
    
    myNode.addChild(material)
    myNode.addChild(rebar)
    
    Group2 = coin.SoGroup()
    Switch.addChild(Group2)
    
    tr = coin.SoTransform()
    tr.translation.setValue(0,0,0)
    tr.rotation.setValue(0,0,1 , 0.00   )
    Group2.addChild(tr)
    array1 = coin.SoArray() 
    Group2.addChild(array1)
    array1.origin = 'CENTER'
    array1.numElements1 = num
    array1.separation1.setValue(spacing,0,0)
    array1.addChild(myNode)
    
    return Switch

class SqaureFooting():
    def __init__(self, obj):
        #obj.addProperty("App::PropertyLength","Length","Size","Length of the Footing").Length=1000.0
        obj.addProperty("App::PropertyLength","Width","Size","Width of the Footing").Width=1000.0
        obj.addProperty("App::PropertyLength","Height","Size", "Height of the Footing").Height=150.0
        obj.addProperty("App::PropertyLength","Covering","Footing", "Covering of the concrete").Covering=50.0

        obj.addProperty("App::PropertyInteger","number","Rebars", "Covering of the concrete").number=8
        obj.addProperty("App::PropertyInteger","diameter","Rebars", "Covering of the concrete").diameter=12
        obj.addProperty("App::PropertyPlacement","Placement","Base", "Covering of the concrete")
        #obj.addProperty("Part::PropertyPartShape","Shape","Base","")
        obj.Proxy = self
    def onChanged(self, fp, prop):
        pass
    def execute(self, fp):
        pass
        #import Part
        #p = Part.makeSphere(10)
        #p.Placement = fp.Placement
        #fp.Shape = p

class ViewProviderSqaureFooting:
    def __init__(self, obj):
        '''Set this object to the proxy object of the actual view provider'''
        obj.addProperty("App::PropertyColor","Color","Footing Concrete","Color of the Footing").Color=(0.000,0.667,1.000)
        obj.Proxy = self
    
    
    def attach(self, obj):
        
        self.shaded = coin.SoGroup()
        self.shaded.setName('Footing')
        self.concSep = coin.SoSeparator()
        #self.color = coin.SoBaseColor()
        self.material = coin.SoMaterial()
        
        
        
        tr = coin.SoTransform()
        self.concrete=coin.SoCube() 
        self.concSep.addChild(tr)

        self.concSep.addChild(self.material)
        self.concSep.addChild(self.concrete)

        self.shaded.addChild(self.concSep)
        self.rebar1Sep = coin.SoSeparator()
        self.shaded.addChild(self.rebar1Sep)
        self.rebar2Sep = coin.SoSeparator()
        self.shaded.addChild(self.rebar2Sep)

        obj.addDisplayMode(self.shaded,"Shaded");

        self.onChanged(obj,"Color")
    
    
    
    def updateData(self, fp, prop):
        '''If a property of the handled feature has changed we have the chance to handle this here'''
        # fp is the handled feature, prop is the name of the property that has changed
        #l = fp.getPropertyByName("Length")
        placement=fp.getPropertyByName("Placement")
        x = placement.Base.x
        y = placement.Base.y
        z = placement.Base.z
        #tr = self.getChild(0)
        #Msg(tr)
        
        w = fp.getPropertyByName("Width")
        h = fp.getPropertyByName("Height")
        l =w
        self.concrete.width = float(l)
        self.concrete.height = float(w)
        self.concrete.depth = float(h)
        tr = self.concSep.getChild(0)
        #Msg(tr)
        tr.translation.setValue(x+0,y+0,z+float(h)/2)
        
        dia = fp.getPropertyByName("diameter")
        num = fp.getPropertyByName("number")
        covering = fp.getPropertyByName("Covering")
        A = float(h) - 2*float(covering)-float(dia)/2
        B = float(w)- 2*float(covering)- float(dia)
        R = 2.*float(dia)
        spacing = (B - 2*R)/(num-1)
        tr1 =  coin.SoTransform()
        tr1.translation.setValue(x+0,y+0,z+float(covering)+float(dia)/2)
        self.rebar1Sep.removeAllChildren()
        self.rebar1Sep.addChild(tr1)
        self.rebar1Sep.addChild(creteRebarU(dia=dia , A=A,  B=B ,num = num,spacing=spacing))
        
        tr2 =  coin.SoTransform()
        tr2.translation.setValue(x+0,y+0,z+float(covering)+float(dia)/2 +float(dia) )
        tr2.rotation.setValue(coin.SbRotation(coin.SbVec3f(0.0, 0.0, 1.0), pi/2.0))
        self.rebar2Sep.removeAllChildren()
        self.rebar2Sep.addChild(tr2)
        self.rebar2Sep.addChild(creteRebarU(dia=dia , A=A-float(dia),  B=B ,num = num,spacing=spacing))


    def getDisplayModes(self,obj):
        '''Return a list of display modes.'''
        modes=[]
        modes.append("Shaded")
        #modes.append("Wireframe")
        return modes
    
    def getDefaultDisplayMode(self):
        '''Return the name of the default display mode. It must be defined in getDisplayModes.'''
        return "Shaded"
    
    def setDisplayMode(self,mode):
        return mode
    
    def onChanged(self, vp, prop):
        '''Here we can do something when a single property got changed'''
        if prop == "Color":
            c = vp.getPropertyByName("Color")
            self.material.transparency.setValue(0.60)
            self.material.diffuseColor.setValue(c[0],c[1],c[2])
    
    
    def __getstate__(self):
        return None
    
    def __setstate__(self,state):
        return None

def makeSqaureFooting():
    doc = FreeCAD.ActiveDocument
    a=doc.addObject("App::FeaturePython","Footing")
    SqaureFooting(a)
    ViewProviderSqaureFooting(a.ViewObject)
    return a


if __name__=='__main__':
    #makeSqaureFooting()
    import datetime
    a = datetime.datetime.now()
    for i in range(0,10):
        for j in range(0,3):
            Footing = makeSqaureFooting()
            Footing.Height = 300
            Footing.Placement.Base=FreeCAD.Vector(i*4000,j*4000,0)
    
    FreeCAD.ActiveDocument.recompute()
    b = datetime.datetime.now()
    Msg(b-a)
    Msg('\n')
    Msg('Done!\n\n')

'''
sel = FreeCADGui.Selection.getSelection()[0]
Msg(sel.ViewObject.IV)
'''
SquareFooting_coin.png
SquareFooting_coin.png (441.94 KiB) Viewed 1694 times
User avatar
chakkree
Posts: 327
Joined: Tue Jun 30, 2015 12:58 am
Location: Bangkok Thailand

Re: Test Create ArchRebar2 Object

Post by chakkree »

Test add rebars to Arch.Structure by using Armatures property
Now in the experiment for the concept only, not completed.
ContBeam_Rebar_01.png
ContBeam_Rebar_01.png (380.31 KiB) Viewed 1540 times
source code:
ContBeam.py
(7.68 KiB) Downloaded 62 times
Rebars.py
(12.92 KiB) Downloaded 56 times
User avatar
chakkree
Posts: 327
Joined: Tue Jun 30, 2015 12:58 am
Location: Bangkok Thailand

Re: Test Create ArchRebar2 Object

Post by chakkree »

Now, Arch WB already have new rebar object that can be based on DWire and hosted to Structure.
I'm think, I will close this session and use "Rebar Addon for FreeCAD" (amrit3701) for better.

link to : Dev logs of Rebar Addon for FreeCAD - GSoC project
Post Reply