{"id":1470,"date":"2012-12-11T14:42:19","date_gmt":"2012-12-11T14:42:19","guid":{"rendered":"http:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/?page_id=1470"},"modified":"2012-12-20T00:45:25","modified_gmt":"2012-12-20T00:45:25","slug":"code-1-add-title","status":"publish","type":"page","link":"https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/code\/code-1-add-title\/","title":{"rendered":"Ca3(PO4)2 Metempsychosis"},"content":{"rendered":"<p>SUBDIVIDE MESH TO ATTRACTORS<\/p>\n<p>&nbsp;<\/p>\n<p>import rhinoscriptsyntax as rs<\/p>\n<p>&#8220;&#8221;&#8221;<br \/>\nScript written by Ezio Blasetti<br \/>\nScript copyrighted by algorithmicdesign.net<br \/>\nScript version Sunday, June 25, 2011 1:07:59 PM<br \/>\n###########################################################################################<br \/>\nThis is a simple recursive subdivision example with use of python classes.<br \/>\nIt takes as an input a single mesh, the recursive limmit &amp; a scale for the recursive vector<br \/>\n&#8220;&#8221;&#8221;<\/p>\n<p>def averagePts(pts):<br \/>\nav = [0,0,0]<br \/>\nfor pt in pts:<br \/>\nav = rs.PointAdd(av,pt)<br \/>\nav = rs.VectorScale(av, 1\/(len(pts)))<br \/>\nreturn rs.PointAdd(av,[0,0,0])<\/p>\n<p>def normalizeAverageDistanceFactor2Attractors(pts, attrs):<br \/>\nlistReturn = []<br \/>\nallAvDist = []<br \/>\nminAvDist = 5000000000<br \/>\nmaxAvDist = -1<br \/>\nfor pt in pts:<br \/>\nsumDist = 0<br \/>\nfor attr in attrs:<br \/>\nsumDist += rs.Distance(pt, attr)<br \/>\navDist = sumDist \/ len(attrs)<br \/>\nallAvDist.append(avDist)<br \/>\nif avDist &lt; minAvDist : minAvDist = avDist<br \/>\nif avDist &gt; maxAvDist : maxAvDist = avDist<br \/>\nfor i in range(len(pts)):<br \/>\nlistReturn.append( (allAvDist[i] &#8211; minAvDist)\/(maxAvDist &#8211; minAvDist) )<br \/>\nreturn listReturn<\/p>\n<p>def intAverageDistanceFactor2Attractors(pts, attrs, max):<br \/>\nlistReturn = []<br \/>\nallAvDist = []<br \/>\nminAvDist = 5000000000<br \/>\nmaxAvDist = -1<br \/>\nfor pt in pts:<br \/>\nsumDist = 0<br \/>\nfor attr in attrs:<br \/>\nsumDist += rs.Distance(pt, attr)<br \/>\navDist = sumDist \/ len(attrs)<br \/>\nallAvDist.append(avDist)<br \/>\nif avDist &lt; minAvDist : minAvDist = avDist<br \/>\nif avDist &gt; maxAvDist : maxAvDist = avDist<br \/>\nfor i in range(len(pts)):<br \/>\nlistReturn.append( max &#8211; int( ((allAvDist[i] &#8211; minAvDist)\/(maxAvDist &#8211; minAvDist))*(max+1)) )<br \/>\nreturn listReturn<\/p>\n<p>class sierpinski():<br \/>\ndef __init__(self, seedMeshGUID, ATTRS, MAX):<br \/>\n#here we initiate the class by matching the inputs to the variables in the class<br \/>\nself.id = seedMeshGUID<br \/>\nself.max = MAX<br \/>\n#here we make sure that the mesh is made only of triangles<br \/>\nif rs.MeshQuadCount(self.id)&gt;0:<br \/>\nrs.MeshQuadsToTriangles(self.id)<br \/>\n#here we store other information we&#8217;ll need later into a few more variables<br \/>\nself.vtxs = rs.MeshVertices(self.id)<br \/>\nself.fVtxs = rs.MeshFaceVertices(self.id)<br \/>\nself.normals = rs.MeshFaceNormals(self.id)<br \/>\ncenters = rs.MeshFaceCenters(self.id)<br \/>\nself.faceRecursionCount = intAverageDistanceFactor2Attractors(centers, ATTRS, MAX)<br \/>\nself.newVtxs = self.vtxs[:]<\/p>\n<p>def subdivideFace(self, faceIndex):<br \/>\n&#8220;&#8221;&#8221;<br \/>\nthis function returns a new mesh -pyramid- for a given faceIndex of a mesh<br \/>\n&#8220;&#8221;&#8221;<br \/>\n#here we initiate two new lists to contain the vertices and faceVertices of the pyramid<br \/>\n#newMeshVTXs = []<br \/>\nnewMeshFaceVTXs = []<br \/>\n#################################################<br \/>\nfaceToSubdivide = self.fVtxs[faceIndex]<br \/>\n#here we call a custom function to calculate the new vertex from the centroid<br \/>\n#centroidPt = self.newPoint4Subd(faceIndex, scale)<br \/>\npt01 = averagePts([self.vtxs[faceToSubdivide[0]], self.vtxs[faceToSubdivide[1]]])<br \/>\npt12 = averagePts([self.vtxs[faceToSubdivide[1]], self.vtxs[faceToSubdivide[2]]])<br \/>\npt20 = averagePts([self.vtxs[faceToSubdivide[2]], self.vtxs[faceToSubdivide[0]]])<br \/>\n#we append in the vertex list the vertices of the parent face<br \/>\n#self.newVtxs.append(self.vtxs[faceToSubdivide[0]])<br \/>\n#self.newVtxs.append(self.vtxs[faceToSubdivide[1]])<br \/>\n#self.newVtxs.append(self.vtxs[faceToSubdivide[2]])<br \/>\n#and the newly calculated centroid<br \/>\nself.newVtxs.append(pt01)<br \/>\nself.newVtxs.append(pt12)<br \/>\nself.newVtxs.append(pt20)<br \/>\n#here we append the faceVertices of the new pyramid<br \/>\n#self.fVtxs.pop(faceIndex)<br \/>\nnewMeshFaceVTXs.append((faceToSubdivide[0],len(self.newVtxs)-3\u00a0 ,len(self.newVtxs)-1))<br \/>\nnewMeshFaceVTXs.append((len(self.newVtxs)-3\u00a0 ,faceToSubdivide[1],len(self.newVtxs)-2))<br \/>\nnewMeshFaceVTXs.append((len(self.newVtxs)-1\u00a0 ,len(self.newVtxs)-2\u00a0 ,faceToSubdivide[2]))<br \/>\nnewMeshFaceVTXs.append((len(self.newVtxs)-3\u00a0 ,len(self.newVtxs)-2\u00a0 ,len(self.newVtxs)-1))<br \/>\n#we make the new mesh -pyramid- and return its GUID<br \/>\nreturn newMeshFaceVTXs<\/p>\n<p>def subdivide(self):<br \/>\n&#8220;&#8221;&#8221;<br \/>\nthis function will loop through all the faces of the mesh and subdivide them<br \/>\n&#8220;&#8221;&#8221;<br \/>\nfor j in range(self.max):<br \/>\nfaceCount = len(self.fVtxs)<br \/>\nrs.EnableRedraw(False)<br \/>\n#flip = 1<br \/>\nnewFaceVtxs = []<br \/>\nnewFaceRecCount = []<br \/>\nfor i in range(faceCount):<br \/>\n#scale = scale*flip<br \/>\n#this is where we make the new pyramids for each face<br \/>\ncurrentRec = self.faceRecursionCount[i]<br \/>\nif self.faceRecursionCount[i]&gt;j:<br \/>\nr = self.subdivideFace(i)<br \/>\nfor i in range(len(r)):<br \/>\nnewFaceRecCount.append(currentRec-1)<br \/>\nnewFaceVtxs.extend(r)<br \/>\nelse:<br \/>\nnewFaceVtxs.append(self.fVtxs[i])<br \/>\nnewFaceRecCount.append(currentRec-1)<\/p>\n<p>#flip = flip*(-1)<br \/>\n#this is where we join all the pyramids in one mesh<br \/>\n#self.joinChildren()<br \/>\nrs.DeleteObject(self.id)<br \/>\nself.id = rs.AddMesh(self.newVtxs,newFaceVtxs)<br \/>\nrs.EnableRedraw(True)<br \/>\n#here we update the information of vtxs,faces,normals in the class variables<br \/>\nself.vtxs = rs.MeshVertices(self.id)<br \/>\nself.fVtxs = rs.MeshFaceVertices(self.id)<br \/>\nself.normals = rs.MeshFaceNormals(self.id)<br \/>\nself.newVtxs = self.vtxs[:]<br \/>\nself.faceRecursionCount = newFaceRecCount<\/p>\n<p>def joinChildren(self):<br \/>\n&#8220;&#8221;&#8221;<br \/>\nthis function will join all the meshes in the self.childrenIDs:<br \/>\nwhich means it will create a new mesh whih contains all the vertices and faces<br \/>\nof those meshes and delete the old ones. This function basically calculates (sorts out) the two lists<br \/>\nrequired to make a mesh, namely the mesh vertices and the mesh faceVertices.<br \/>\nExample:<br \/>\nmesh0VTXs\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 = [[0,0,0],[1,0,0],[0,1,0],[0,0,1]]<br \/>\nmesh0FaceVTXs\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 = [[3,0,1],[3,1,2],[3,2,0]]<br \/>\nmesh1VTXs\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 = [[0,0,0],[-1,0,0],[0,1,0],[0,0,-1]]<br \/>\nmesh1FaceVTXs\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 = [[3,0,1],[3,1,2],[3,2,0]]<br \/>\nResult:<br \/>\nmesh0and1VTXs\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 = [[0,0,0],[1,0,0],[0,1,0],[0,0,1],[0,0,0],[-1,0,0],[0,1,0],[0,0,-1]]<br \/>\nmesh0and1FaceVTXs\u00a0\u00a0 = [[3, 0, 1],[3, 1, 2],[3, 2, 0],[7, 0, 5],[7, 5, 2],[7, 2, 0]]<br \/>\n&#8220;&#8221;&#8221;<br \/>\n#here we initiate two new lists to contain the vertices and faceVertices of the new &#8216;sum&#8217; mesh<br \/>\nnewMeshVTXs = []<br \/>\nnewMeshFaceVTXs = []<br \/>\narrayOfMeshes = self.childrenIDs<br \/>\n#for every mesh in the array of meshes to join<br \/>\nfor currentMesh in arrayOfMeshes:<br \/>\n#we store its vertices in a list<br \/>\nmeshVTXs = rs.MeshVertices(currentMesh)<br \/>\n#and extend the list of the new vertices by adding all of these vertices inside<br \/>\nnewMeshVTXs.extend(meshVTXs)<br \/>\n#we store the faceVertices of the current mesh in a list<br \/>\nmeshFaceVTXs = rs.MeshFaceVertices(currentMesh)<br \/>\n#we loop through each face in faceVertices list<br \/>\nfor face in meshFaceVTXs:<br \/>\n#start a new list for the adjusted face<br \/>\nnewFace = []<br \/>\n#loop through each index (vertex) in the current face<br \/>\nfor index in face:<br \/>\n#find the right index for the current vertex and append it in the newFace list<br \/>\nnewFace.append(newMeshVTXs.index(meshVTXs[index]))<br \/>\n#append the newFace in the list of new faces<br \/>\nnewMeshFaceVTXs.append(newFace)<br \/>\n#delete the old meshes<br \/>\nrs.DeleteObjects(arrayOfMeshes)<br \/>\n#restart the children list<br \/>\nself.childrenIDs = []<br \/>\n#delete the parent mesh<br \/>\nrs.DeleteObject(self.id)<br \/>\n#add the new mesh &#8211; joined children<br \/>\nself.id = rs.AddMesh(newMeshVTXs, newMeshFaceVTXs)<br \/>\n#return true since everything went good<br \/>\nreturn True<\/p>\n<p>def main():<br \/>\nmesh = rs.GetObject(&#8220;select the mesh to subdivive&#8221;,rs.filter.mesh)<br \/>\nmax = rs.GetInteger(&#8220;Enter the number of maximum recursion: &#8220;, 4, 1, 8)<br \/>\nstrAttrs = rs.GetObjects(&#8220;select some attractors&#8221;,rs.filter.point)<br \/>\nattrs = []<br \/>\nfor str in strAttrs:<br \/>\nattrs.append(rs.PointCoordinates(str))<br \/>\n###################################################################<br \/>\nmySierpinski = sierpinski(mesh, attrs, max)<br \/>\n###################################################################<br \/>\nmySierpinski.subdivide()<\/p>\n<p>main()<\/p>\n<p>&nbsp;<\/p>\n<p>DRAW LINES ON MESH<\/p>\n<p><a href=\"http:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-content\/uploads\/2012\/12\/draw.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft  wp-image-1749\" title=\"draw\" src=\"http:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-content\/uploads\/2012\/12\/draw-1024x837.png\" alt=\"\" width=\"430\" height=\"351\" srcset=\"https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-content\/uploads\/2012\/12\/draw-1024x837.png 1024w, https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-content\/uploads\/2012\/12\/draw-300x245.png 300w, https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-content\/uploads\/2012\/12\/draw.png 1672w\" sizes=\"auto, (max-width: 430px) 100vw, 430px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>FREI OTTO<\/p>\n<p><a href=\"http:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-content\/uploads\/2012\/12\/frei_otto.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft  wp-image-1750\" title=\"frei_otto\" src=\"http:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-content\/uploads\/2012\/12\/frei_otto-1024x478.png\" alt=\"\" width=\"430\" height=\"201\" srcset=\"https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-content\/uploads\/2012\/12\/frei_otto-1024x478.png 1024w, https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-content\/uploads\/2012\/12\/frei_otto-300x140.png 300w, https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-content\/uploads\/2012\/12\/frei_otto.png 1096w\" sizes=\"auto, (max-width: 430px) 100vw, 430px\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>SUBDIVIDE MESH TO ATTRACTORS &nbsp; import rhinoscriptsyntax as rs &#8220;&#8221;&#8221; Script written by Ezio Blasetti Script copyrighted by algorithmicdesign.net Script version Sunday, June 25, 2011 1:07:59 PM ########################################################################################### This is a simple recursive subdivision example with use of python classes. It takes as an input a single mesh, the recursive limmit &amp; a scale for [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":9,"menu_order":0,"comment_status":"closed","ping_status":"open","template":"","meta":{"footnotes":""},"class_list":["post-1470","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-json\/wp\/v2\/pages\/1470","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-json\/wp\/v2\/comments?post=1470"}],"version-history":[{"count":10,"href":"https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-json\/wp\/v2\/pages\/1470\/revisions"}],"predecessor-version":[{"id":1754,"href":"https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-json\/wp\/v2\/pages\/1470\/revisions\/1754"}],"up":[{"embeddable":true,"href":"https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-json\/wp\/v2\/pages\/9"}],"wp:attachment":[{"href":"https:\/\/www.new-territories.com\/blog\/ncertainties\/col12\/wp-json\/wp\/v2\/media?parent=1470"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}