disdyakis development
Forum rules
and Helpful information
and Helpful information
IMPORTANT: Please click here and read this first, before asking for help
Also, be nice to others! Read the FreeCAD code of conduct!
Also, be nice to others! Read the FreeCAD code of conduct!
disdyakis development
The disdyakis dodecahedron is at the heart of Paul D Burley’s book the Sacred Sphere and matches the biblically described properties of the Ark.
I design to lend its form to a greenhouse that is capable of floating in the event of a flood or worse.
I like to think of it as a Cossac bio-domicile. I’m a long way off from that goal but this is the reason I decided to teach myself FreeCAD.
I’ve made a number of attempts at re-producing this Catalan solid and met with some success but I can’t help but think that there are superior ways to achieve a result. Maybe deductive booleans from a solid, I don’t know, I did not get what I was looking for when I attempted that.
I’ve tried to use the surface workbench (0.19) to “skin” the attached frame of interlaced sketches but have come to the conclusion that this tool was not designed for that purpose.
My question is how would you produce a disdyakis dodecahedron in FreeCAD?
https://infogalactic.com/info/Disdyakis_dodecahedron
- Attachments
-
- solid_surface.FCStd
- (37.81 KiB) Downloaded 21 times
___
ordinary by design
ordinary by design
-
- Veteran
- Posts: 5505
- Joined: Thu Apr 05, 2018 1:53 am
Re: disdyakis development
Thanks for that.
If I understand correctly I should be able to switch my construction sketches to blue - reference mode - and use them to generate a datum plane on which to sketch a scalene triangle and repeat until complete.
I'll give it a go.
Salute for the insight.
If I understand correctly I should be able to switch my construction sketches to blue - reference mode - and use them to generate a datum plane on which to sketch a scalene triangle and repeat until complete.
I'll give it a go.
Salute for the insight.
___
ordinary by design
ordinary by design
Re: disdyakis development
The blue construction lines aren't visible outside of Sketcher, and thus cannot be used for creating a DatumPlane. However, you can use a normal sketch for that; if you don't use it for feature generation, it doesn't have the usual restrictions such as no crossings or T-joins.
A Sketcher Lecture with in-depth information is available in English, auf Deutsch, en français, en español.
-
- Veteran
- Posts: 3112
- Joined: Thu Sep 24, 2020 10:31 pm
- Location: Hawaii
- Contact:
Re: disdyakis development
Once you have the coordinates of the vertices, it's just work... I made a sketch representing stereographic projection
Inverting that gave the coordinates of the vertices. I got bored after creating the edges. Creating wires, then faces look to be very tedious. Given the coordinates, there has to be a much quicker way to generate the solid - maybe the convex hull of the points.
Anyhow the following code in the python console generates the coordinates and the wireframe from the file below with just the sketch.
Here are the 26 vertices if someone else wants to construct the object
You actually only need to create a 45 degree wedge about the z-axis. One reflection and a fourfold polar-pattern would finish it (within common face errors). Entertaining construction...
Inverting that gave the coordinates of the vertices. I got bored after creating the edges. Creating wires, then faces look to be very tedious. Given the coordinates, there has to be a much quicker way to generate the solid - maybe the convex hull of the points.
Anyhow the following code in the python console generates the coordinates and the wireframe from the file below with just the sketch.
Code: Select all
def stereo(xyVector, sphereRadius):
''' return the inverse stereographic projection of the xy=plane vector xyVector to a sphere radius sphereRadius'''
x = xyVector.x
y = xyVector.y
factor = sphereRadius / (x * x + y * y + sphereRadius * sphereRadius)
return App.Vector(factor * 2* sphereRadius*x, factor * 2*sphereRadius* y, factor * (x * x + y * y - sphereRadius*sphereRadius))
sk = App.ActiveDocument.getObject('Sketch')
skg = sk.Geometry
i = 0
vertices = []
points = [ p for p in skg if p.TypeId == 'Part::GeomPoint']
radius = sk.Constraints[20].Value
for p in points:
vertex = stereo(App.Vector(p.X, p.Y, 0), radius)
vertices.append(vertex)
#print(f' {i} : ({p.X}, {p.Y}) {vertex}')
i += 1
allvertices =[App.Vector(0.,0, -radius), App.Vector(0,0, radius) ]
rot90 = App.Rotation(App.Vector(0, 0, 1), 90)
rot180 = App.Rotation(App.Vector(0, 0, 1), 180)
rot270= App.Rotation(App.Vector(0, 0, 1), 270)
for v in vertices:
vx = v.x
vy = v.y
vz = v.z
V = App.Vector(vx, vy, vz)
allvertices.extend([V, rot90.multVec(V), rot180.multVec(V), rot270.multVec(V)])
i=0
pva =[]
for v in allvertices:
print(v)
pv =App.ActiveDocument.addObject("Part::Vertex","dydVertex"+str(i))
pv.X = v.x
pv.Y = v.y
pv.Z = v.z
pva.append(pv)
for i in range(2,6):
Part.show(Part.makeLine(allvertices[1],allvertices[i]))
for i in range(14,18):
Part.show(Part.makeLine(allvertices[1],allvertices[i]))
for i in range(10,14):
Part.show(Part.makeLine(allvertices[0],allvertices[i]))
for i in range(22,26):
Part.show(Part.makeLine(allvertices[0],allvertices[i]))
for i in range(0,4):
Part.show(Part.makeLine(allvertices[2+i],allvertices[14+i]))
Part.show(Part.makeLine(allvertices[10+i],allvertices[22+i]))
Part.show(Part.makeLine(allvertices[10+i],allvertices[6+i]))
Part.show(Part.makeLine(allvertices[6+i],allvertices[14+i]))
Part.show(Part.makeLine(allvertices[22+i],allvertices[18+i]))
Part.show(Part.makeLine(allvertices[18+i],allvertices[2+i]))
Part.show(Part.makeLine(allvertices[18+i],allvertices[6+i]))
Part.show(Part.makeLine(allvertices[22+i],allvertices[10+(i+1)%4]))
Part.show(Part.makeLine(allvertices[18+i],allvertices[6+(i+1)%4]))
Part.show(Part.makeLine(allvertices[2+i],allvertices[14+(i+1)%4]))
Part.show(Part.makeLine(allvertices[6+i],allvertices[2+i])) #
Part.show(Part.makeLine(allvertices[6+i],allvertices[2+(i-1)%4])) #
Part.show(Part.makeLine(allvertices[6+i],allvertices[22+ i])) #
Part.show(Part.makeLine(allvertices[6+i],allvertices[22+(i-1)%4])) #
Code: Select all
Vector (0.0, 0.0, -100.0)
Vector (0.0, 0.0, 100.0)
Vector (57.73502691896254, 57.73502691896249, 57.73502691896271)
Vector (-57.735026918962475, 57.735026918962554, 57.73502691896271)
Vector (-57.73502691896255, -57.73502691896248, 57.73502691896271)
Vector (57.735026918962475, -57.735026918962554, 57.73502691896271)
Vector (100.0, 2.484506934232031e-14, 0.0)
Vector (-2.640608849817178e-15, 100.0, 0.0)
Vector (-100.0, -1.2598601350846777e-14, 0.0)
Vector (2.640608849817178e-15, -100.0, 0.0)
Vector (70.71067811865505, 0.0, -70.71067811865446)
Vector (1.5700924586837817e-14, 70.71067811865505, -70.71067811865446)
Vector (-70.71067811865505, 8.65956056235497e-15, -70.71067811865446)
Vector (-1.5700924586837817e-14, -70.71067811865505, -70.71067811865446)
Vector (70.71067811865471, 0.0, 70.71067811865481)
Vector (1.5700924586837742e-14, 70.71067811865471, 70.71067811865481)
Vector (-70.71067811865471, 8.659560562354928e-15, 70.71067811865481)
Vector (-1.5700924586837742e-14, -70.71067811865471, 70.71067811865481)
Vector (70.71067811865477, 70.71067811865474, 0.0)
Vector (-70.71067811865473, 70.71067811865478, 0.0)
Vector (-70.71067811865478, -70.71067811865473, 0.0)
Vector (70.71067811865473, -70.71067811865478, 0.0)
Vector (57.73502691896248, 57.735026918962525, -57.73502691896274)
Vector (-57.73502691896251, 57.7350269189625, -57.73502691896274)
Vector (-57.73502691896249, -57.73502691896252, -57.73502691896274)
Vector (57.73502691896251, -57.7350269189625, -57.73502691896274)
- Attachments
-
- dydakis.FCStd
- (7.11 KiB) Downloaded 22 times
-
- Screen Shot 2021-07-15 at 2.12.37 PM.png (20.78 KiB) Viewed 1281 times
-
- Veteran
- Posts: 3112
- Joined: Thu Sep 24, 2020 10:31 pm
- Location: Hawaii
- Contact:
Re: disdyakis development
Gave up on the scripting - used Part|ShapeBuilder to make a shell and a solid.
- Attachments
-
- dydakis2.FCStd
- (233.67 KiB) Downloaded 25 times
-
- Veteran
- Posts: 3112
- Joined: Thu Sep 24, 2020 10:31 pm
- Location: Hawaii
- Contact:
Re: disdyakis development
Well, this isnt quite right. It is close. It took me a while to figure out why. The area is correct, but the volume is wrong and so are the side lengths. Id wrongly assumed that the vertices lay on a sphere, which they don’t quite, so the stereographic projection (at least only one) is not enough to reconstruct the solid.
Fun while it lasted…
Fun while it lasted…
-
- Veteran
- Posts: 3112
- Joined: Thu Sep 24, 2020 10:31 pm
- Location: Hawaii
- Contact:
Re: disdyakis development
To learn some Topological data scripting https://wiki.freecadweb.org/Topological_data_scripting I constructed the disdyakis dodecahedron from vertex data in netlib http://www.netlib.org/polyhedra/37 For some strange reason, the data was translated and rotation in some fashion. Anyhow, this method works, though I would have preferred a purely geometric construction.
There's a whole database of exotic regular solids in netlib. With some effort one could parse the datafiles and construct any of them in FreeCAD.
Code: Select all
''' Create a Disdyakis dodecahedron from vertex data'''
import Part
from math import sqrt
scaleFactor = 1.0 # =1 => middle edge length =1
#data from http://www.netlib.org/polyhedra/37 https://en.wikipedia.org/wiki/Disdyakis_dodecahedron
#these vertices are tilted and translated for no obvious reason
vertices = [
App.Vector(2.6133122279038238, -4.3663082302150226, -7.140305645693695),
App.Vector(2.8343891236796766, -5.0800291876449795, -7.163837801596551),
App.Vector(2.8419869679386627, -4.0977146372750205, -6.4812216553007066), # -X
App.Vector(2.886667096895415, -5.0456133045766546, -6.1657984433994139),
App.Vector(3.009894100904886, -4.0067697532409839, -7.6621114168954244), #+ Z
App.Vector(3.1604567932353163, -4.8973184004605509, -8.091359576603294),
App.Vector(3.1728458528068138, -3.2955543914174693, -6.9782843659031492),
App.Vector(3.3382971302138604, -5.6314377767564596, -7.1346547570869689), # -Y
App.Vector(3.3513947319758703, -3.9380673488691023, -5.9579217083010231),
App.Vector(3.6408427234443935, -3.7812913170646378, -7.9936075282074776),
App.Vector(3.6831062016314853, -5.5655035406455466, -6.4746655586534303),
App.Vector(3.6907040458918208, -4.5831889902828067, -5.7920494123621763),
App.Vector(3.8510133346080949, -5.4745586566032474, -7.655555320247756),
App.Vector(3.8662090231277648, -3.5099295558781736, -6.2903230276597041),
App.Vector(4.0265183118308238, -4.4012992222023037, -8.1538289355476461),
App.Vector(4.0341161560950081, -3.4189846718394306, -7.4712127892567944),
App.Vector(4.0763796342737318, -5.2031968954186892, -5.952270819699509),
App.Vector(4.3658276257560316, -5.046420863604471, -7.9879566396081482),
App.Vector(4.3789252275208671, -3.3530504357319652, -6.8112235908168941), #+Y
App.Vector(4.544376504923661, -5.6889338210650479, -6.9675939820056528),
App.Vector(4.5567655644914461, -4.0871698120259693, -5.8545187713067436),
App.Vector(4.7073282568126512, -4.9777184592536349, -6.283766931010124), #- Z
App.Vector(4.83055526083214, -3.9388749079095933, -7.7800799045112476),
App.Vector(4.8752353897887335, -4.8867735752081337, -7.4646566926071458), #+X
App.Vector(4.8828332340508313, -3.904459024847932, -6.7820405463160945),
App.Vector(5.1039101298205366, -4.6181799822850979, -6.8055727022155921)]
# vertices making up faces
# No_of vertices (3), vertex_index, vertex_index, vertex_index indices offset by 50 in data table i.e 50 -> vertices[0]
vlist =[
(3, 52, 56, 50),
(3, 50, 56, 54),
(3, 54, 55, 50),
(3, 50, 55, 51),
(3, 51, 53, 50),
(3, 50, 53, 52),
(3, 65, 72, 59),
(3, 59, 72, 64),
(3, 64, 55, 59),
(3, 59, 55, 54),
(3, 54, 56, 59),
(3, 59, 56, 65),
(3, 73, 69, 67),
(3, 67, 69, 62),
(3, 62, 55, 67),
(3, 67, 55, 64),
(3, 64, 72, 67),
(3, 67, 72, 73),
(3, 60, 53, 57),
(3, 57, 53, 51),
(3, 51, 55, 57),
(3, 57, 55, 62),
(3, 62, 69, 57),
(3, 57, 69, 60),
(3, 60, 69, 66),
(3, 66, 69, 71),
(3, 71, 70, 66),
(3, 66, 70, 61),
(3, 61, 53, 66),
(3, 66, 53, 60),
(3, 73, 72, 75),
(3, 75, 72, 74),
(3, 74, 70, 75),
(3, 75, 70, 71),
(3, 71, 69, 75),
(3, 75, 69, 73),
(3, 65, 56, 68),
(3, 68, 56, 63),
(3, 63, 70, 68),
(3, 68, 70, 74),
(3, 74, 72, 68),
(3, 68, 72, 65),
(3, 52, 53, 58),
(3, 58, 53, 61),
(3, 61, 70, 58),
(3, 58, 70, 63),
(3, 63, 56, 58),
(3, 58, 56, 52)]
faceList = []
def makeFacesVlist(edgeList, start = 50):
tList =edgeList[1:4]
eeList =[]
for i in range(3):
jstart = tList[i] -start
jend = tList[(i+1)%3] - start
#print (f'{jstart} {jend}')
edge = Part.Edge(Part.LineSegment(vertices[jstart], vertices[jend]))
ee = App.ActiveDocument.addObject("Part::Feature", "Edge")
ee.Shape = edge
eeList.append(edge)
added = eobj.addObject(ee)
#print(eeList)
App.ActiveDocument.recompute()
w = Part.Wire(eeList)
face = Part.Face(w)
ff = App.ActiveDocument.addObject("Part::Feature", "Face")
ff.Shape = face
added = fobj.addObject(ff)
faceList.append(ff.Shape)
#find rotation and translation to orient the object on the z-axis, center at origin
xhat = (vertices[23] - vertices[2]).normalize()
yhat = (vertices[18] - vertices[7]).normalize()
zhat = (vertices[4] - vertices[21]).normalize()
rot = App.Rotation(xhat, yhat, zhat).inverted()
center = App.Vector(0., 0., 0.)
for v in vertices:
center = center + v
center = center/len(vertices)
vertices_cen = [ v - center for v in vertices] #center on origin
vertices_rot = [scaleFactor*rot.multVec(v) for v in vertices_cen] #scale and rotate
print(f'Circumradius = {((vertices_rot[4] - vertices_rot[21])/2).Length}')
print(f'Edge Lengths {(vertices_rot[2]-vertices_rot[6]).Length} {(vertices_rot[6]-vertices_rot[0]).Length} {(vertices_rot[0]-vertices_rot[2]).Length}')
#print(f'Edge Lengths {(vertices_rot[14]-vertices_rot[5]).Length} {(vertices_rot[5]-vertices_rot[9]).Length} {(vertices_rot[9]-vertices_rot[14]).Length}')
shortestEdgeLength = (vertices_rot[0]-vertices_rot[2]).Length
vertices = vertices_rot
eobj = App.ActiveDocument.addObject("App::DocumentObjectGroup","EdgeGroup")
fobj = App.ActiveDocument.addObject("App::DocumentObjectGroup","FaceGroup")
vobj = App.ActiveDocument.addObject("App::DocumentObjectGroup","VertexGroup")
pva=[]
#create vertices
for v in vertices:
pv =App.ActiveDocument.addObject("Part::Vertex","Vertex")
added = vobj.addObject(pv)
pv.X = v.x
pv.Y = v.y
pv.Z = v.z
pva.append(pv)
#create edges and faces
for edge in vlist:
makeFacesVlist(edge)
#make solid
solid = Part.Solid(Part.Shell(faceList))
solidobj = App.ActiveDocument.addObject("Part::Feature", "Disdyakis dodecahedron")
solidobj.Shape= solid
App.ActiveDocument.recompute()
#check some parameters
print(f'Volume = {solidobj.Shape.Volume} Area = {solidobj.Shape.Area}')
print(f'Volume_theory {shortestEdgeLength**3*sqrt(3*(2194 + 1513*sqrt(2)))/7} Area_theory {shortestEdgeLength**2*sqrt(783+ 436*sqrt(2))*6/7}')
- Attachments
-
- polyfromvertices.FCStd
- (220.59 KiB) Downloaded 22 times
-
- Screen Shot 2021-07-17 at 3.19.32 PM.png (20.56 KiB) Viewed 1137 times
Re: disdyakis development
Maybe you need a special feature, go into Macros_recipes and Code_snippets, Topological_data_scripting.
My macros on Gist.github here complete macros Wiki and forum.
My macros on Gist.github here complete macros Wiki and forum.
-
- Veteran
- Posts: 3112
- Joined: Thu Sep 24, 2020 10:31 pm
- Location: Hawaii
- Contact:
Re: disdyakis development
More user interface on those Macros - but nothing quite as exotic as this polyhedron.
Turning code into reality, I 3D printed one. The image shows it sitting on a dodecahedral box I made as an exercise in compound angle cutting. I was testing out a broken Festool Kapex saw I was given, which I rebuilt.
Turning code into reality, I 3D printed one. The image shows it sitting on a dodecahedral box I made as an exercise in compound angle cutting. I was testing out a broken Festool Kapex saw I was given, which I rebuilt.