Pyramid addition to Geometric Primitives

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!
Tilarta
Posts: 12
Joined: Sat Aug 10, 2019 4:53 am
Contact:

Pyramid addition to Geometric Primitives

Postby Tilarta » Fri Aug 16, 2019 2:02 am

Many times now I've wanted to make a Pyramid type shape for various reasons and the process in converting a wedge to a Pyramid is rather laborious/tedious.
Also, the wedge when created is never vertical, which is an added annoyance, as I have to rotate the axis before performing any other tasks.

Then there is the additional complication of moving the points around to match the shape of the object the pyramid will be anchored to:
DBwedge2Point.png
DBwedge2Point.png (20.08 KiB) Viewed 230 times
To make this process a whole lot easier/more efficient, I am requesting that a preformatted Pyramid shape be added to Geometric primitives.
I can then tailor this shape to the task needed without having to mess around with the point values relating to the apex point and just move the base/height points around instead.
chrisb
Posts: 16935
Joined: Tue Mar 17, 2015 9:14 am

Re: Pyramid addition to Geometric Primitives

Postby chrisb » Fri Aug 16, 2019 7:29 am

You can achieve the same result with a draft point and a sketch.
Nevertheless I would support this with an arbitrary regular polygon as base shape.
Syres
Posts: 297
Joined: Thu Aug 09, 2018 11:14 am

Re: Pyramid addition to Geometric Primitives

Postby Syres » Fri Aug 16, 2019 5:42 pm

Tilarta wrote:
Fri Aug 16, 2019 2:02 am
Many times now I've wanted to make a Pyramid type shape for various reasons and the process in converting a wedge to a Pyramid is rather laborious/tedious.
While you're waiting for the proper fix to be applied to the source code, you might find a use for this crude macro but it's only tested on 0.18.3 and above on Windows:

Code: Select all

from PySide import QtCore, QtGui
from PySide.QtGui import QLineEdit, QRadioButton
import Draft

class makePyramid():
    def __init__(self):
        self.dialog = None
        self.s1 = None
		
        # Make dialog box
        self.dialog = QtGui.QDialog()
        self.dialog.resize(350,200)
        self.dialog.setWindowTitle("Create a Pyramid Solid")
        la = QtGui.QVBoxLayout(self.dialog)
        t1 = QtGui.QLabel("Length of Base (mm)")
        la.addWidget(t1)
        self.s1 = QtGui.QLineEdit()
        self.s1.setText("10")
        la.addWidget(self.s1)

        t2 = QtGui.QLabel("Width of Base (mm)")
        la.addWidget(t2)
        self.s2 = QtGui.QLineEdit()
        self.s2.setText("10")
        la.addWidget(self.s2)

        t3 = QtGui.QLabel("Point Height (mm)")
        la.addWidget(t3)
        self.s3 = QtGui.QLineEdit()
        self.s3.setText("10")
        la.addWidget(self.s3)

        self.radio1 = QtGui.QRadioButton("Radius Corners")
        self.radio2 = QtGui.QRadioButton("Non-radius Corners")

        self.radio2.setChecked(True)
        la.addWidget(self.radio1)
        la.addWidget(self.radio2)

        # Add OK / Cancel buttons
        okbox = QtGui.QDialogButtonBox(self.dialog)
        okbox.setOrientation(QtCore.Qt.Horizontal)
        okbox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
        la.addWidget(okbox)
        QtCore.QObject.connect(okbox, QtCore.SIGNAL("accepted()"), self.proceed)
        QtCore.QObject.connect(okbox, QtCore.SIGNAL("rejected()"), self.close)
        QtCore.QMetaObject.connectSlotsByName(self.dialog)
        self.dialog.show()
        self.dialog.exec_()

    def proceed(self):

        if self.s1.text()=="" or self.s2.text()=="" or self.s3.text()=="":
            FreeCAD.Console.PrintError("All three dimension text boxes must be completed\n")
        else:
            fLength = float(self.s1.text())
            fWidth = float(self.s2.text())
            fHeight = float(self.s3.text())
            fXpos = float(self.s1.text())/2
            fYpos = float(self.s2.text())/2
            fRadius = (fLength + fWidth) /100
            tRadius = str(fRadius)+" mm"
            pl = FreeCAD.Placement()
            pl.Rotation.Q = (0.0,-0.0,-0.0,1.0)
            pl.Base = FreeCAD.Vector(-fXpos, -fYpos, 0.0)
            rec = Draft.makeRectangle(length=fLength,height=fWidth,placement=pl,face=False,support=None)
            Draft.autogroup(rec)
            point = Draft.makePoint(0.0,0.0,fHeight)
            Draft.autogroup(point)
            from FreeCAD import Base
            App.ActiveDocument.addObject('Part::Loft','PyramidLoft')
            App.ActiveDocument.ActiveObject.Sections=[App.ActiveDocument.Rectangle, App.ActiveDocument.Point, ]
            App.ActiveDocument.ActiveObject.Solid=True
            App.ActiveDocument.ActiveObject.Ruled=False
            App.ActiveDocument.ActiveObject.Closed=False
            if self.radio1.isChecked():
                App.ActiveDocument.getObject("Rectangle").FilletRadius = tRadius
            App.activeDocument().recompute()
            Gui.ActiveDocument.getObject("Point").Visibility=False
            App.ActiveDocument.getObject("Point").Label = 'PyramidPoint'
            Gui.ActiveDocument.getObject("Rectangle").Visibility=False
            App.ActiveDocument.getObject("Rectangle").Label = 'PyramidBase'
            Gui.SendMsgToActiveView("ViewFit")
            Gui.activeDocument().activeView().viewDimetric()
            App.ActiveDocument.addObject('Part::Feature','Pyramid').Shape=App.ActiveDocument.PyramidLoft.Shape
            App.ActiveDocument.ActiveObject.Label=App.ActiveDocument.Pyramid.Label
            Gui.ActiveDocument.ActiveObject.ShapeColor=Gui.ActiveDocument.Pyramid.ShapeColor
            Gui.ActiveDocument.ActiveObject.LineColor=Gui.ActiveDocument.Pyramid.LineColor
            Gui.ActiveDocument.ActiveObject.PointColor=Gui.ActiveDocument.Pyramid.PointColor
            Gui.ActiveDocument.ActiveObject.DiffuseColor=Gui.ActiveDocument.Pyramid.DiffuseColor
            App.ActiveDocument.removeObject("PyramidLoft")
            App.ActiveDocument.removeObject("Rectangle")
            App.ActiveDocument.removeObject("Point")
            App.ActiveDocument.recompute()
            self.close()

    def close(self):
        self.dialog.hide()


makePyramid()

OS: Windows 7
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.18.16131 (Git)
Build type: Release
Branch: releases/FreeCAD-0-18
Hash: 3129ae4296e40ed20e7b3d460b86e6969acbe1c3
Python version: 3.6.6
Qt version: 5.6.2
Coin version: 4.0.0a
OCC version: 7.3.0
Locale: English/UnitedKingdom (en_GB)

OS: Windows 7 SP 1 (6.1)
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.19.17651 (Git)
Build type: Release
Branch: master
Hash: 16c26cb3b1cd7209ea8efc8cb30b3b18fd80cf95
Python version: 3.6.8
Qt version: 5.12.1
Coin version: 4.0.0a
OCC version: 7.3.0
Locale: English/United Kingdom (en_GB)
TheMarkster
Posts: 995
Joined: Thu Apr 05, 2018 1:53 am

Re: Pyramid addition to Geometric Primitives

Postby TheMarkster » Fri Aug 16, 2019 8:27 pm

Extrude a regular polygon with 4 sides. Apply this formula to the Extrude taper angle property:

Code: Select all

57.29578 * pi / 180 * atan(2 * LengthFwd / Base.Circumradius / sqrt(2)) - 90deg
This requires circumradius of the polygon to be used to determine the base of the pyramid. Through some experimentation I have found if you set the circumradius to s / 2 * sqrt(2) you get s for the pyramid base size (side length dimension).

So, if you want base = 10 mm and height = 20 mm you extrude to length forward = 20 mm, then set the circumradius of the polygon to 10 / 2 * sqrt(2).

This only works with 4 sided polygons. I haven't worked out the general formula for n-sided polygons.

Edit: had base and height backwards.
User avatar
DeepSOIC
Posts: 6689
Joined: Fri Aug 29, 2014 12:45 am
Location: Saint-Petersburg, Russia

Re: Pyramid addition to Geometric Primitives

Postby DeepSOIC » Fri Aug 16, 2019 9:45 pm

I think we might want a full workbench of primitives. You know, prisms, pyramids, regular polyhedra, other polyhedra, geodesic domes, ellipsoids, paraboloids, gyroids, logarithmic and hyperbolic spirals, gaussians ...
Joyas
Posts: 475
Joined: Sat Jul 12, 2014 8:39 pm

Re: Pyramid addition to Geometric Primitives

Postby Joyas » Sat Aug 17, 2019 1:52 am

DeepSOIC wrote:
Fri Aug 16, 2019 9:45 pm
I think we might want a full workbench of primitives. You know, prisms, pyramids, regular polyhedra, other polyhedra, geodesic domes, ellipsoids, paraboloids, gyroids, logarithmic and hyperbolic spirals, gaussians ...
I agree, I tried something like that two years ago, but I couldn't because I didn't know how handle thee drawing functions and it was too difficult for me.

It was called "pwned workbench" or "parts with new enhanced details". It was planned to have not only primitives (icosahedron spheres, antiprisms...), but also modifiers, for example, an array over the vertexes of a dodecahedron or a icosahedron. Also It has a function which takes the edges of a body and converts it into a thick wires.

Most of its functions can be done with other workbenches (Lattice2, Sketcher, Draft and Part), but I wanted something easy for beginners.

If someone find it useful, use its code.
I prefer JavaScript, I don't like Python indentation.