Macro Geodesic Dome
Description |
---|
This macro creates a geodesic dome Macro version: 01.00 Last modified: 2015-01-04 Author: Ulrich Brammer |
Author |
Ulrich Brammer |
Download |
None |
Links |
Macros recipes How to install macros How to customize toolbars |
Macro Version |
01.00 |
Date last modified |
2015-01-04 |
FreeCAD Version(s) |
None |
Default shortcut |
None |
See also |
None |
Description
This macro creates a geodesic dome shell. The dome radius and the frequency parameter will be set at creation time.
Installation
Save the following script as MacroGeodesicDome.py to your macro directory.
Script
MacroGeodesicDome.py
# -*- coding: utf-8 -*-
# ************************************************************************
# * Copyright (c)2015 Ulrich Brammer <ulrich1a[at]users.sourceforge.net> *
# * *
# * This file is a supplement to the FreeCAD CAx development system. *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This software is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this macro; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ************************************************************************
from PySide import QtCore, QtGui
import FreeCAD, FreeCADGui, math, Part
from FreeCAD import Base
def makeDomeShape(domeRad, ny):
#semi-global variables
a = 0 #Strutlength of underlying icosahedron:
icoFaces = [] # collects faces of the underlying icosahedron
domeFaces = [] # collects the faces of the geodesic dome
def makeFreqFaces(fPt, sPt, thPt, ny = 1):
# makes the geodesic dome faces out of the points of an
# icosahedron triangle
b = a/ny # length of frequent triangles
# definition of direction vectors
growVec = (sPt - fPt)
# growVec = (fPt - sPt)
growVec.multiply(1.0/ny)
crossVec = (thPt - sPt)
# crossVec = (sPt - thPt)
crossVec.multiply(1.0/ny)
for k in range(ny):
kThirdPt = fPt + growVec * (k+0.0)
dThirdPt = Base.Vector(kThirdPt.x, kThirdPt.y, kThirdPt.z)
dThirdPt = dThirdPt.normalize().multiply(domeRad)
kSecPt = fPt + growVec * (k+1.0)
dSecPt = Base.Vector(kSecPt.x, kSecPt.y, kSecPt.z)
dSecPt = dSecPt.normalize().multiply(domeRad)
# thirdEdge = Part.makeLine(kSecPt, kThirdPt)
# thirdEdge = Part.makeLine(dSecPt, dThirdPt)
for l in range(k+1):
firstPt = kSecPt + crossVec *(l+1.0)
dFirstPt = firstPt.normalize().multiply(domeRad)
secPt = kSecPt + crossVec *(l+0.0)
dSecPt =secPt.normalize().multiply(domeRad)
thirdPt = kThirdPt + crossVec *(l+0.0)
dThirdPt = thirdPt.normalize().multiply(domeRad)
#thirdEdge = Part.makeLine(secPt, thirdPt)
thirdEdge = Part.makeLine(dSecPt, dThirdPt)
# Part.show(thirdEdge)
if l > 0:
print("in l: ", l, " mod 2: ", l%2)
# What to do here?
#secEdge = Part.makeLine(oThirdPt,thirdPt)
secEdge = Part.makeLine(doThirdPt,dThirdPt)
# Part.show(secEdge)
#thirdEdge = Part.makeLine(secPt, thirdPt)
#thirdEdge = Part.makeLine(dSecPt, dThirdPt)
# Part.show(thirdEdge)
triWire = Part.Wire([firstEdge, secEdge, thirdEdge])
# Part.show(triWire)
triFace = Part.Face(triWire)
domeFaces.append(triFace)
#Part.show(triFace)
oThirdPt = thirdPt
doThirdPt = oThirdPt.normalize().multiply(domeRad)
# oFirstPt = firstPt
#firstEdge = Part.makeLine(thirdPt,firstPt)
firstEdge = Part.makeLine(dThirdPt,dFirstPt)
oFirstEdge = firstEdge
#secEdge = Part.makeLine(firstPt,secPt)
secEdge = Part.makeLine(dFirstPt,dSecPt)
#Part.show(firstEdge)
#Part.show(secEdge)
#Part.show(thirdEdge)
triWire = Part.Wire([firstEdge, secEdge, thirdEdge])
triFace = Part.Face(triWire)
domeFaces.append(triFace)
#Part.show(triFace)
a=(4.0*domeRad)/math.sqrt(2.0*math.sqrt(5.0)+10.0)
# icoAngle: angle of vertices of icosahedron points
# not a north or south pole
icoAngle = math.atan(0.5)
icoLat = domeRad * math.sin(icoAngle)
latRad = domeRad * math.cos(icoAngle)
ang36 = math.radians(36.0)
# Calculation all points of the icosahedron
icoPts = []
icoPts.append(Base.Vector(0.0, 0.0, domeRad))
for i in range(10):
icoCos = latRad * math.cos(i*ang36)
icoSin = latRad * math.sin(i*ang36)
if i%2 == 0:
icoPts.append(Base.Vector(icoSin, icoCos, icoLat))
else:
icoPts.append(Base.Vector(icoSin, icoCos, -icoLat))
icoPts.append(Base.Vector(0.0, 0.0, -domeRad))
# making the faces of the icosahedron
thirdPt = icoPts[9]
thirdEdge = Part.makeLine(icoPts[0],thirdPt)
for i in range(5):
j = i*2+1
firstEdge = Part.makeLine(thirdPt,icoPts[j])
secEdge = Part.makeLine(icoPts[j],icoPts[0])
triWire = Part.Wire([firstEdge, secEdge, thirdEdge])
triFace = Part.Face(triWire)
icoFaces.append(triFace)
# Part.show(triFace)
makeFreqFaces(icoPts[j], icoPts[0], thirdPt, ny)
thirdEdge = Part.makeLine(icoPts[0],icoPts[j])
thirdPt = icoPts[j]
thirdPt = icoPts[9]
secPt = icoPts[10]
thirdEdge = Part.makeLine(secPt,thirdPt)
for i in range(10):
j = i+1
firstEdge = Part.makeLine(thirdPt,icoPts[j])
secEdge = Part.makeLine(icoPts[j],secPt)
triWire = Part.Wire([firstEdge, secEdge, thirdEdge])
triFace = Part.Face(triWire)
icoFaces.append(triFace)
#Part.show(triFace)
makeFreqFaces(icoPts[j], secPt, thirdPt, ny)
thirdPt = secPt
secPt = icoPts[j]
thirdEdge = Part.makeLine(secPt,thirdPt)
thirdPt = icoPts[10]
thirdEdge = Part.makeLine(icoPts[11],thirdPt)
for i in range(5):
j = i*2+2
firstEdge = Part.makeLine(thirdPt,icoPts[j])
secEdge = Part.makeLine(icoPts[j],icoPts[11])
triWire = Part.Wire([firstEdge, secEdge, thirdEdge])
triFace = Part.Face(triWire)
icoFaces.append(triFace)
#Part.show(triFace)
makeFreqFaces(icoPts[j], icoPts[11], thirdPt, ny)
thirdEdge = Part.makeLine(icoPts[11],icoPts[j])
thirdPt = icoPts[j]
# Shell of a corresponding icosahedron
newShell = Part.Shell(icoFaces)
#Part.show(newShell)
# Shell of the geodesic dome
#domeShell = Part.Shell(domeFaces)
#Part.show(domeShell)
return Part.Shell(domeFaces)
# Shere with radius of geodesic dome for debugging purposes
# testSphere = Part.makeSphere(domeRad)
#Part.show(testSphere)
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(477, 188)
self.dia = Dialog
self.gridLayoutWidget = QtGui.QWidget(Dialog)
self.gridLayoutWidget.setGeometry(QtCore.QRect(19, 19, 440, 141))
self.gridLayoutWidget.setObjectName("gridLayoutWidget")
self.gridLayout = QtGui.QGridLayout(self.gridLayoutWidget)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.label = QtGui.QLabel(self.gridLayoutWidget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
#self.lineEdit = QtGui.QLineEdit(self.gridLayoutWidget)
fui = FreeCADGui.UiLoader()
self.lineEdit = fui.createWidget("Gui::InputField")
self.lineEdit.setObjectName("lineEdit")
self.gridLayout.addWidget(self.lineEdit, 0, 1, 1, 1)
self.label_2 = QtGui.QLabel(self.gridLayoutWidget)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1)
self.lineEdit_2 = QtGui.QLineEdit(self.gridLayoutWidget)
self.lineEdit_2.setObjectName("lineEdit_2")
self.gridLayout.addWidget(self.lineEdit_2, 1, 1, 1, 1)
self.label_3 = QtGui.QLabel(self.gridLayoutWidget)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1)
self.buttonBox = QtGui.QDialogButtonBox(self.gridLayoutWidget)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons \
(QtGui.QDialogButtonBox.Cancel