Thank you mario52 for your post. I have benefited much from your macros. They have helped me in learning Python and FC.
I too have been playing with polyhedra. Below is code that I recently completed that will produce the "great rhombicuboctahedron", incorrectly called a "truncated cuboctahedron". I have been working on finding the object from which the "great rhombicuboctahedro" can be found by truncation.
This project has raised a question that I will ask here, perhaps not the preferred posting site but here goes.
If the code below is placed in the Macro editor and executed the code is successful in producing the "great rhombicuboctahedro" as desired. If the code is placed in the Python console an error (invalid syntax) is generated, an error that I cannot rectify. Is there an explanation for this?
Code: Select all
# code to generate the great rhombicuboctahedron
import FreeCAD as App
import Part
import math
import numpy as np
import FreeCADGui
v=App.Vector
red=1.0,0.0,0.0,0.0
green=0.0,1.0,0.0,0.0
blue=0.0,0.0,1.0,0.0
yellow=(1.0,1.0,0.0)
theLengthOfEdge=10.0
# (±1, ±(1 + √2), ±(1 + 2√2)) vertices for edge length of 2.0
print("12 squares")
print(" 8 hexagons")
print("6 octagons")
print("26 total")
A1=float(1)
print("A1",A1)
B1=float(1+math.sqrt(2))
print("B1",B1)
C1=float(1+2*math.sqrt(2))
print("C1",C1)
#ABC
#ACB
#BAC
#BCA
#CAB
#CBA
#ABC
v11=v(A1,B1,C1)
v21=v(A1,B1,-C1)
v31=v(A1,-B1,C1)
v41=v(-A1,B1,C1)
v51=v(A1,-B1,-C1)
v61=v(-A1,-B1,C1)
v71=v(-A1,B1,-C1)
v81=v(-A1,-B1,-C1)
#ACB
v12=v(A1,C1,B1)
v22=v(A1,C1,-B1)
v32=v(A1,-C1,B1)
v42=v(-A1,C1,B1)
v52=v(A1,-C1,-B1)
v62=v(-A1,-C1,B1)
v72=v(-A1,C1,-B1)
v82=v(-A1,-C1,-B1)
#BAC
v13=v(B1,A1,C1)
v23=v(B1,A1,-C1)
v33=v(B1,-A1,C1)
v43=v(-B1,A1,C1)
v53=v(B1,-A1,-C1)
v63=v(-B1,-A1,C1)
v73=v(-B1,A1,-C1)
v83=v(-B1,-A1,-C1)
#BCA
v14=v(B1,C1,A1)
v24=v(B1,C1,-A1)
v34=v(B1,-C1,A1)
v44=v(-B1,C1,A1)
v54=v(B1,-C1,-A1)
v64=v(-B1,-C1,A1)
v74=v(-B1,C1,-A1)
v84=v(-B1,-C1,-A1)
#CAB
v15=v(C1,A1,B1)
v25=v(C1,A1,-B1)
v35=v(C1,-A1,B1)
v45=v(-C1,A1,B1)
v55=v(C1,-A1,-B1)
v65=v(-C1,-A1,B1)
v75=v(-C1,A1,-B1)
v85=v(-C1,-A1,-B1)
#CBA
v16=v(C1,B1,A1)
v26=v(C1,B1,-A1)
v36=v(C1,-B1,A1)
v46=v(-C1,B1,A1)
v56=v(C1,-B1,-A1)
v66=v(-C1,-B1,A1)
v76=v(-C1,B1,-A1)
v86=v(-C1,-B1,-A1)
theV=[v11,v21,v31,v41,v51,v61,v71,v81,v12,v22,v32,v42,v52,v62,v72,v82,v13,v23,v33,v43,v53,v63,v73,v83,v14,v24,v34,v44,v54,v64,v74,v84,v15,v25,v35,v45,v55,v65,v75,v85,v16,v26,v36,v46,v56,v66,v76,v86]
print("theV",len(theV))
def reverse(L):
return(L[::-1])
def rotateLeft(T,n):
return( T[n:] + T[:n])
def rotateRight(T,n):
return( T[-n:] + T[:-n])
def cross(a, b):
x = a[1]*b[2] - a[2]*b[1]
y=a[2]*b[0] - a[0]*b[2]
z=a[0]*b[1] - a[1]*b[0]
return(x,y,z)
def dot(v1,v2):
theDot=v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]
return(theDot)
def mag(v):
theMag=math.sqrt(v.x*v.x+v.y*v.y+v.z*v.z)
return theMag
def cleanDuplicates(L):
M=L
for i in L:
k=i
for j in range(len(i)-1):
k=rotateRight(k,1)
try:
M.remove(k)
except:
pass
k=reverse(i)
for j in range(len(i)):
k=rotateRight(k,1)
try:
M.remove(k)
except:
pass
return(M)
def displayEdges(E):
print("displaying edges")
for i in E:
v1=i[0]
v2=i[1]
Edge=Part.LineSegment(v1,v2).toShape()
Wire=Part.Wire(Edge)
Part.show(Wire)
#displayEdges(theEdges)
def uniqueList(L):
bin=[L[0]]
for i in L:
flag=1
for j in bin:
if i==j:
flag=0
if flag==1:
bin.append(i)
return(bin)
def isIn(obj,theList):
for i in theList:
if obj==i:
return(True)
return(False)
def makeEdges(theV):
bin=[] # each edge is a pair of indices to two vertices - edge length is 2
for i in range(len(theV)):
for j in range(len(theV)):
if i!=j:
theMag=mag(theV[i]-theV[j])
if theMag<2.1 and theMag>1.9:
bin.append((i,j))
return(uniqueList(bin))
def makeLegs(theEdges):
bin=[] # combine two edges that meet each other
for i in theEdges:
for j in theEdges:
if i!=j and not (i[0]==j[1] and i[1]==j[0]):
if i[1]==j[0]:
bin.append((i,j))
if i[0]==j[1]:
bin.append((j,i))
return(uniqueList(bin))
theLegs90=[]
theLegs60=[]
theLegs45=[]
def placeLegs(angle,Edge):
if angle==45:
theLegs45.append(Edge)
elif angle==60:
theLegs60.append(Edge)
elif angle==90:
theLegs90.append(Edge)
else:
print("placeLegs()",angle)
def makeLegLists(theLegs):
for i in theLegs:
v1=theV[i[0][0]]-theV[i[0][1]]
v1=v(v1)
v2=theV[i[1][0]]-theV[i[1][1]]
v2=v(v2)
m1=mag(v1)
m2=mag(v2)
C=dot(v1,v2)/(m1*m2)
if C>1.0:
C=1.0
if C< -1.0:
C= -1.0
A=math.acos(C)
A*= 180.0/math.pi
A=np.round(A,4)
A=int(A)
placeLegs(A,i)
def splitLegs(L):
bin=[]
for i in L:
for j in i:
bin.append(j)
return(uniqueList(bin))
def attachEdges(L0,L1):
bin=[]
for i in L0:
for j in L1:
if i[-1]==j[0] and i[-2]!=j[1]:
term=i+j
bin.append(term)
# print(term)
return(bin)
def removeDups(L):
bin = []
for i in L:
term=[]
for j in i:
if j not in term:
term.append(j)
bin.append(term)
return(bin)
def displayFaces(V,theColor):
for i in V:
thePoints=[]
for j in i:
V=(theLengthOfEdge/2.0)*v(theV[j])
thePoints.append(V)
makeFace(thePoints,theColor)
theFaces=[]
theGuiFaces=[]
def makeFace(theList,theColor): # P are Vertex.Point
thePart=Part.makeFilledFace(Part.makePolygon(theList, True).Edges)
if thePart.isNull(): print("cannot make face!")
thePartObj=App.ActiveDocument.addObject('Part::Feature','Face')
thePartObj.Shape=thePart
gad = Gui.activeDocument()
theGuiObj = gad.getObject(thePartObj.Name)
theGuiObj.ShapeColor=theColor
theFaces.append(thePartObj.Shape)
def makeShell(theFaces):
thePart=Part.Shell(theFaces)
if thePart.isNull():print("No shell!")
thePartObject=App.ActiveDocument.addObject('Part::Feature','Shell')
thePartObject.Shape=thePart.removeSplitter()
# shell=App.ActiveDocument.Shell.Shape
# if shell.ShapeType != 'Shell': raise RuntimeError('Part object is not a shell')
# _=Part.Solid(shell)
_=Part.Solid(thePartObject.Shape)
if _.isNull(): raise RuntimeError('Failed to create solid')
App.ActiveDocument.addObject('Part::Feature','Solid').Shape=_.removeSplitter()
##########################################################################
doc=App.newDocument("great rhombicuboctahedron")
theEdges=makeEdges(theV)
print("theEdges",int(len(theEdges)/2))
theLegs=makeLegs(theEdges)
makeLegLists(theLegs)
theV90=theEdges90=splitLegs(theLegs90)
for i in range(3):
theV90=attachEdges(theV90,theEdges90)
theV90=cleanDuplicates(theV90)
print("theV90",len(theV90))
theList=removeDups(theV90)
displayFaces(theList,blue)
theV60=theEdges60=splitLegs(theLegs60)
for i in range(5):
theV60=attachEdges(theV60,theEdges60)
theV60=cleanDuplicates(theV60)
print("theV60",len(theV60))
theList=removeDups(theV60)
displayFaces(theList,yellow)
theV45=theEdges45=splitLegs(theLegs45)
for i in range(7):
theV45=attachEdges(theV45,theEdges45)
theV45=cleanDuplicates(theV45)
print("theV45",len(theV45))
theList=removeDups(theV45)
displayFaces(theList,red)
makeShell(theFaces)
doc.recompute()
Gui.SendMsgToActiveView("ViewFit")