Demonstrating coding abilities

Have some feature requests, feedback, cool stuff to share, or want to know where FreeCAD is going? This is the place.
Forum rules
Be nice to others! Read the FreeCAD code of conduct!
User avatar
amrit3701
Posts: 303
Joined: Mon Jun 13, 2016 5:37 pm

Demonstrating coding abilities

Postby amrit3701 » Tue Mar 28, 2017 5:04 pm

Hi,

Is the bug fixing the only way to demonstrate coding abilities for GSoC? Is it acceptable if I submit a piece of code related to my proposed GSoC project "Rebar addon for FreeCAD"?

Regards,
ickby
Posts: 2978
Joined: Wed Oct 05, 2011 7:36 am

Re: Demonstrating coding abilities

Postby ickby » Wed Mar 29, 2017 5:23 am

Hello,

bug fixing is one way, but doing some work for your proposal already is also welcome. We just like to see that you understand FreeCADs architecture, and that you are able to add code into the infrastructure.
User avatar
amrit3701
Posts: 303
Joined: Mon Jun 13, 2016 5:37 pm

Re: Demonstrating coding abilities

Postby amrit3701 » Thu Mar 30, 2017 1:25 pm

ickby wrote: bug fixing is one way, but doing some work for your proposal already is also welcome. We just like to see that you understand FreeCADs architecture, and that you are able to add code into the infrastructure.
I have coded a fully parametric rectangular footing rebar mesh and sharing its Python code below as a proof of concept for my GSoC proposal:

Code: Select all

import ArchCommands,ArchComponent,FreeCAD
from FreeCAD import Vector, Rotation
import Draft
import DraftGeomUtils



def _make_circular_rebar(points, dia, rebars):
    """ This function takes the points of the lines, diameter of the rebar
        and then return all the generated rebars. """
    lines = []
    lines.append(Part.Line(points[1],points[0]))
    spath = Part.Shape(lines)
    edge = Part.__sortEdges__(spath.Edges)
    wpath = Part.Wire(edge)
    wire = Part.Wire(spath)
    bpoint = points[0]
    bvec = points[1].sub(points[0]).normalize()
    circle = Part.makeCircle(dia/2,bpoint,bvec)
    circle = Part.Wire(circle)
    rebars.append(wire.makePipeShell([circle],True,False,2))
    return rebars



class _rectangular_footing_mesh(ArchComponent.Component):
    def __init__(self,obj):
        # Import ArchCompent properties.
        ArchComponent.Component.__init__(self,obj)
        # Initialize all the parameters of rectangular footing mesh.
        obj.addProperty("App::PropertyDistance", "DiaX", "Rebars along X-axis", "Diameter of rebars").DiaX = 20
        obj.addProperty("App::PropertyQuantity", "BarsX", "Rebars along X-axis", "Number of rebars").BarsX = 10
        obj.addProperty("App::PropertyDistance", "SpacingX", "Rebars along X-axis", "Spacing between rebars").SpacingX = 100
        obj.addProperty("App::PropertyDistance", "OffsetX", "Rebars along X-axis", "Edge cover from top rebars").OffsetX = 50
        obj.addProperty("App::PropertyDistance", "DiaY", "Rebars along Y-axis", "Diameter of rebar").DiaY = 12
        obj.addProperty("App::PropertyQuantity", "BarsY", "Rebars along Y-axis", "Number of rebars").BarsY = 10
        obj.addProperty("App::PropertyDistance", "Spacing2", "Rebars along Y-axis", "Spacing between rebars").Spacing2 = 150
        obj.addProperty("App::PropertyDistance", "OffsetY", "Rebars along Y-axis", "Edge cover from bottom rebars").OffsetY = 50


    def execute(self,obj):
        if self.clone(obj):
            return

        # Calculating the length of bottom and top rebars.
        length1 = 2*obj.OffsetY+(obj.Spacing2*(int(obj.BarsY)-1))
        length2 = 2*obj.OffsetX+(obj.SpacingX*(int(obj.BarsX)-1))

        import Part
        bottom_rebar_pts = []
        upper_rebar_pts = []

        # Calculating the distance of the second bottom rebar from origin.
        spacing_points = obj.OffsetX + obj.SpacingX

        # Calculating all value of points in space of bottom rebar and append it into bottom_rebar_pts array.
        bottom_rebar_pts.append([Vector(0, obj.OffsetX,0), Vector(length1, obj.OffsetX, 0)])
        for i in range(int(obj.BarsX)-1):
            bottom_rebar_pts.append([Vector(0, spacing_points, 0), Vector(length1, spacing_points, 0)])
            # Increment the spacing_points by spacing present between the rebars.
            spacing_points += obj.SpacingX

        # Calculating the distance of the second top rebar from origin.
        spacing_points = obj.OffsetY + obj.Spacing2
        # Calculating all value of points in space of top rebar and append it into bottom_rebar_pts array.
        upper_rebar_pts.append([Vector(obj.OffsetY, 0, obj.DiaX/2+obj.DiaY/2), Vector(obj.OffsetY, length2, obj.DiaX/2+obj.DiaY/2)])
        for i in range(int(obj.BarsY)-1):
            upper_rebar_pts.append([Vector(spacing_points, 0, obj.DiaX/2+obj.DiaY/2), Vector(spacing_points, length2, obj.DiaX/2+obj.DiaY/2)])
            spacing_points += obj.Spacing2

        bars = []
        # Transform points of rebar to 3D circular shape.
        for i in bottom_rebar_pts:
            _make_circular_rebar(i, obj.DiaX, bars)
        # Transform points of rebar to 3D circular shape.
        for i in upper_rebar_pts:
            _make_circular_rebar(i, obj.DiaY, bars)

        # Transform all rebars into a single entity.
        finalshape = Part.makeCompound(bars)
        obj.Shape = finalshape



class _ViewProviderRebar(ArchComponent.ViewProviderComponent):
    def __init__(self,vobj):
        ArchComponent.ViewProviderComponent.__init__(self,vobj)
        # Initializing the color to rebars
        vobj.ShapeColor = (0.67,0.00,0.00)

    def getIcon(self):
        import Arch_rc
        return ":/icons/Arch_Rebar_Tree.svg"


if __name__=="__main__":
    obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Rectangular footing mesh")
    _rectangular_footing_mesh(obj)

    if FreeCAD.GuiUp:
        _ViewProviderRebar(obj.ViewObject)
        FreeCAD.ActiveDocument.recompute()
Below is the output of above code when you run in FreeCAD Python console window:
rectangular_footing.png
rectangular_footing.png (193.82 KiB) Viewed 1478 times
User avatar
yorik
Site Admin
Posts: 12011
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels, Belgium
Contact:

Re: Demonstrating coding abilities

Postby yorik » Fri Mar 31, 2017 2:33 pm

Ok this looks good to me...
This script touches most of what you'll need during the GSOC project
User avatar
cnirbhay
Posts: 116
Joined: Wed Aug 17, 2016 4:24 pm

Re: Demonstrating coding abilities

Postby cnirbhay » Fri Mar 31, 2017 2:34 pm

Wow! That's impressive @Amrit3701. Glad to see your dedication that you've started doing some workout with the FreeCAD architecture. All the best for this project. I'll be happy if this thing gets selected in GSoC, that would boost you with an extra motivation to work more efficiently. :-)
User avatar
bernd
Posts: 10702
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland

Re: Demonstrating coding abilities

Postby bernd » Sun Apr 02, 2017 8:28 pm

yorik wrote:Ok this looks good to me...
This script touches most of what you'll need during the GSOC project
+1

BTW: I get an error on the code ...

Code: Select all

21Standard_TypeMismatch TopoDS::Vertex
Traceback (most recent call last):
  File "<input>", line 49, in execute
  File "<input>", line 7, in _make_circular_rebar
<class 'Part.OCCError'>: 21Standard_TypeMismatch TopoDS::Vertex
OS: Debian GNU/Linux 8.7 (jessie)
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.17.10674 (Git)
Build type: Unknown
Branch: master
Hash: 78d8272d771eb58fff1955ecdde080a639d95b94
Python version: 2.7.9
Qt version: 4.8.6
Coin version: 4.0.0a
OCC version: 7.0.0
User avatar
amrit3701
Posts: 303
Joined: Mon Jun 13, 2016 5:37 pm

Re: Demonstrating coding abilities

Postby amrit3701 » Tue Apr 04, 2017 4:54 pm

bernd wrote: BTW: I get an error on the code ...

Code: Select all

21Standard_TypeMismatch TopoDS::Vertex
Traceback (most recent call last):
  File "<input>", line 49, in execute
  File "<input>", line 7, in _make_circular_rebar
<class 'Part.OCCError'>: 21Standard_TypeMismatch TopoDS::Vertex
Hi Bernd,

This script is not working on latest version of FreeCAD (0.17) but it working fine on all later versions of FreeCAD. Part.__sortEdges__(spath.Edges) is the key behind this error.

BTW, for demo, you should try it on FreeCAD (0.16) version.:)

Regards,
User avatar
amrit3701
Posts: 303
Joined: Mon Jun 13, 2016 5:37 pm

Re: Demonstrating coding abilities

Postby amrit3701 » Sat Apr 08, 2017 2:05 pm

yorik wrote:Ok this looks good to me...
This script touches most of what you'll need during the GSOC project
I am made the dialog box for straight rebar. To run this code you just copy and paste in FreeCAD python console.

Code: Select all

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Straight_rebar_Dialog(object):
    def setupUi(self, Straight_rebar_Dialog):
        self.window = Straight_rebar_Dialog

        Straight_rebar_Dialog.setObjectName(_fromUtf8("Straight_rebar_Dialog"))
        Straight_rebar_Dialog.resize(509, 363)
        self.buttonBox = QtGui.QDialogButtonBox(Straight_rebar_Dialog)
        self.buttonBox.setGeometry(QtCore.QRect(132, 310, 191, 32))
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
        self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
        self.side_cover = QtGui.QLineEdit(Straight_rebar_Dialog)
        self.side_cover.setGeometry(QtCore.QRect(240, 52, 113, 27))
        self.side_cover.setObjectName(_fromUtf8("side_cover"))
        self.front_cover = QtGui.QLineEdit(Straight_rebar_Dialog)
        self.front_cover.setGeometry(QtCore.QRect(240, 121, 113, 27))
        self.front_cover.setObjectName(_fromUtf8("front_cover"))
        self.spacing_label = QtGui.QLabel(Straight_rebar_Dialog)
        self.spacing_label.setGeometry(QtCore.QRect(177, 259, 67, 17))
        self.spacing_label.setObjectName(_fromUtf8("spacing_label"))
        self.amount = QtGui.QSpinBox(Straight_rebar_Dialog)
        self.amount.setGeometry(QtCore.QRect(240, 222, 48, 27))
        self.amount.setObjectName(_fromUtf8("amount"))
        self.amount.setEnabled(False)
        self.front_cover_label = QtGui.QLabel(Straight_rebar_Dialog)
        self.front_cover_label.setGeometry(QtCore.QRect(153, 125, 91, 17))
        self.front_cover_label.setObjectName(_fromUtf8("front_cover_label"))
        self.diameter = QtGui.QLineEdit(Straight_rebar_Dialog)
        self.diameter.setGeometry(QtCore.QRect(240, 157, 113, 27))
        self.diameter.setObjectName(_fromUtf8("diameter"))
        self.amount_label = QtGui.QLabel(Straight_rebar_Dialog)
        self.amount_label.setGeometry(QtCore.QRect(175, 226, 67, 17))
        self.amount_label.setObjectName(_fromUtf8("amount_label"))
        self.spacing = QtGui.QLineEdit(Straight_rebar_Dialog)
        self.spacing.setGeometry(QtCore.QRect(240, 255, 113, 27))
        self.spacing.setObjectName(_fromUtf8("spacing"))
        self.spacing.setEnabled(False)
        self.diameter_label = QtGui.QLabel(Straight_rebar_Dialog)
        self.diameter_label.setGeometry(QtCore.QRect(166, 159, 81, 20))
        self.diameter_label.setObjectName(_fromUtf8("diameter_label"))
        self.amount_radio = QtGui.QRadioButton(Straight_rebar_Dialog)
        self.amount_radio.setGeometry(QtCore.QRect(147, 193, 117, 22))
        self.amount_radio.setObjectName(_fromUtf8("amount_radio"))
        self.spacing_radio = QtGui.QRadioButton(Straight_rebar_Dialog)
        self.spacing_radio.setGeometry(QtCore.QRect(237, 193, 117, 22))
        self.spacing_radio.setObjectName(_fromUtf8("spacing_radio"))
        self.side_cover_label = QtGui.QLabel(Straight_rebar_Dialog)
        self.side_cover_label.setGeometry(QtCore.QRect(159, 57, 71, 17))
        self.side_cover_label.setObjectName(_fromUtf8("side_cover_label"))
        self.bottom_cover = QtGui.QLineEdit(Straight_rebar_Dialog)
        self.bottom_cover.setGeometry(QtCore.QRect(240, 86, 113, 27))
        self.bottom_cover.setObjectName(_fromUtf8("bottom_cover"))
        self.bottom_cover_label = QtGui.QLabel(Straight_rebar_Dialog)
        self.bottom_cover_label.setGeometry(QtCore.QRect(137, 90, 101, 17))
        self.bottom_cover_label.setObjectName(_fromUtf8("bottom_cover_label"))
        self.main_heading = QtGui.QLabel(Straight_rebar_Dialog)
        self.main_heading.setGeometry(QtCore.QRect(188, 12, 121, 31))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.main_heading.setFont(font)
        self.main_heading.setLineWidth(1)
        self.main_heading.setObjectName(_fromUtf8("main_heading"))

        self.retranslateUi(Straight_rebar_Dialog)
        self.amount_radio.clicked.connect(self.amount_radio_clicked)
        self.spacing_radio.clicked.connect(self.spacing_radio_clicked)
        QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), self.accept)
        QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), self.reject)
        QtCore.QMetaObject.connectSlotsByName(Straight_rebar_Dialog)

    def retranslateUi(self, Straight_rebar_Dialog):
        Straight_rebar_Dialog.setWindowTitle(_translate("Straight_rebar_Dialog", "Dialog", None))
        self.spacing_label.setText(_translate("Straight_rebar_Dialog", "Spacing", None))
        self.front_cover_label.setText(_translate("Straight_rebar_Dialog", "Front cover", None))
        self.amount_label.setText(_translate("Straight_rebar_Dialog", "Amount", None))
        self.diameter_label.setText(_translate("Straight_rebar_Dialog", "Diameter", None))
        self.amount_radio.setText(_translate("Straight_rebar_Dialog", "Amount", None))
        self.spacing_radio.setText(_translate("Straight_rebar_Dialog", "Spacing", None))
        self.side_cover_label.setText(_translate("Straight_rebar_Dialog", "Side cover", None))
        self.bottom_cover_label.setText(_translate("Straight_rebar_Dialog", "Bottom cover", None))
        self.main_heading.setText(_translate("Straight_rebar_Dialog", "Fill all the values", None))

    def accept(self):
        self.window.close()
        FreeCAD.Console.PrintMessage("Done!\n")

    def reject(self):
        self.window.close()
        FreeCAD.Console.PrintMessage("Terminate!\n")

    def amount_radio_clicked(self):
        self.spacing.setEnabled(False)
        self.amount.setEnabled(True)

    def spacing_radio_clicked(self):
        self.amount.setEnabled(False)
        self.spacing.setEnabled(True)



class dialog():
   def __init__(self):
       self.d = QtGui.QWidget()
       self.ui = Ui_Straight_rebar_Dialog()
       self.ui.setupUi(self.d)
       self.d.show()

dialog()
Tell me if any improvement is required in the dialog box. Currently, I am working for reinforcement of straight rebar using sketcher.

Regards,
User avatar
yorik
Site Admin
Posts: 12011
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels, Belgium
Contact:

Re: Demonstrating coding abilities

Postby yorik » Sat Apr 08, 2017 6:47 pm

Wouldn't it be interesting to use the Task panel? This gives less clutter to the screen and allows, for example, to more easily pick geometry while the dialog is open

Also, your code seems to be generated from pyuic... It is advisable to keep your ui design as a ui file, otherwise you'll get into a lot of hassle when you want to change something in it.

Check src/Mod/Arch/ArchServer.py, there a re a couple of examples there to do these two things...
User avatar
amrit3701
Posts: 303
Joined: Mon Jun 13, 2016 5:37 pm

Re: Demonstrating coding abilities

Postby amrit3701 » Sun Apr 09, 2017 3:35 pm

yorik wrote:Wouldn't it be interesting to use the Task panel? This gives less clutter to the screen and allows, for example, to more easily pick geometry while the dialog is open
Yes, I also think the Task panel is the better choice than dialog box. It will enrich user experience.
yorik wrote: Also, your code seems to be generated from pyuic... It is advisable to keep your ui design as a ui file, otherwise you'll get into a lot of hassle when you want to change something in it.

Check src/Mod/Arch/ArchServer.py, there a re a couple of examples there to do these two things...
Ok, now I separated my UI file from Python code. Here is my code:
https://github.com/amrit3701/FreeCAD-Reinforcement
task_panel.png
task_panel.png (150.71 KiB) Viewed 1185 times
Tell me if any improvement will require in the UI. :)

Regards,