Source code for compas.datastructures.mesh.planarisation
from__future__importprint_functionfrom__future__importabsolute_importfrom__future__importdivisionfromcompas.geometryimportproject_points_planefromcompas.geometryimportcentroid_pointsfromcompas.geometryimportdistance_point_pointfromcompas.geometryimportdistance_line_linefromcompas.geometryimportbestfit_planefromcompas.utilitiesimportwindow__all__=['mesh_flatness','mesh_planarize_faces',]defmesh_flatness(mesh,maxdev=1.0):"""Computemesh flatness per face.Parameters----------mesh : MeshAmesh object.maxdev : float, optionalAmaximum value for the allowed deviation from flatness.Defaultis ``1.0``.Returns-------dictForeach face, a deviation from *flatness*.Notes-----The"flatness" of a face is expressed as the ratio of the distance betweenthediagonals to the average edge length. For the fabrication of glass panels,forexample, ``0.02`` could be a reasonable maximum value.Warnings--------Thisfunction only works as expected for quadrilateral faces."""dev=[]forfkeyinmesh.faces():points=mesh.face_coordinates(fkey)iflen(points)==3:dev.append(0.0)else:lengths=[distance_point_point(a,b)fora,binwindow(points+points[0:1],2)]length=sum(lengths)/len(lengths)d=distance_line_line((points[0],points[2]),(points[1],points[3]))dev.append((d/length)/maxdev)returndev
[docs]defmesh_planarize_faces(mesh,fixed=None,kmax=100,callback=None,callback_args=None):"""Planarisea set of connected faces.Planarisationis implemented as a two-step iterative procedure. At everyiteration,faces are first individually projected to their best-fit plane,andthen the vertices are projected to the centroid of the disconnectedcornersof the faces.Parameters----------mesh : MeshAmesh object.fixed : list, optional [None]Alist of fixed vertices.kmax : int, optional [100]Thenumber of iterations.d : float, optional [1.0]Adamping factor.callback : callable, optional [None]Auser-defined callback that is called after every iteration.callback_args : list, optional [None]Alist of arguments to be passed to the callback function.Returns-------None"""ifcallback:ifnotcallable(callback):raiseException('The callback is not callable.')fixed=fixedor[]fixed=set(fixed)forkinrange(kmax):positions={key:[]forkeyinmesh.vertices()}forfkeyinmesh.faces():vertices=mesh.face_vertices(fkey)points=[mesh.vertex_coordinates(key)forkeyinvertices]plane=bestfit_plane(points)projections=project_points_plane(points,plane)forindex,keyinenumerate(vertices):positions[key].append(projections[index])forkey,attrinmesh.vertices(True):ifkeyinfixed:continuex,y,z=centroid_points(positions[key])attr['x']=xattr['y']=yattr['z']=zifcallback:callback(k,callback_args)