Languages

Previous versions

1.2
1.1

Source code for openPLM.apps.document3D.mesh

##Copyright 2010 Thomas Paviot (tpaviot@gmail.com)
##
##This file is part of pythonOCC.
##
##pythonOCC is free software: you can redistribute it and/or modify
##it under the terms of the GNU Lesser General Public License as published by
##the Free Software Foundation, either version 3 of the License, or
##(at your option) any later version.
##
##pythonOCC 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 Lesser General Public License for more details.
##
##You should have received a copy of the GNU Lesser General Public License
##along with pythonOCC. If not, see <http://www.gnu.org/licenses/>.

import os, os.path
from kjbuckets import  kjDict

from OCC.Utils.Topology import Topo
from OCC.TopAbs import TopAbs_REVERSED
from OCC.Bnd import Bnd_Box
from OCC.BRepBndLib import BRepBndLib_Add
from OCC.gp import gp_Vec, gp_Pnt
from OCC.BRepMesh import BRepMesh_Mesh
from OCC.BRep import BRep_Tool_Triangulation
from OCC.TopLoc import TopLoc_Location
from OCC.Poly import Poly_Connect
from OCC.StdPrs import StdPrs_ToolShadedShape_Normal
from OCC.TColgp import TColgp_Array1OfDir


triangle_fmt = """ smooth_triangle {
        <%f, %f, %f>, <%f, %f, %f>,
        <%f, %f, %f>, <%f, %f, %f>,
        <%f, %f, %f>, <%f, %f, %f>
      }
    """
vertice_fmt = "%s.vertices.push(new THREE.Vector3(%.4f,%.4f,%.4f));\n"
face_fmt = "%s.faces.push( new THREE.Face3( %i, %i, %i, [ new THREE.Vector3( %.4f, %.4f, %.4f ), new THREE.Vector3( %.4f, %.4f, %.4f ), new THREE.Vector3( %.4f, %.4f, %.4f ) ]  ) );\n"


def get_mesh_precision(shape, quality_factor):
    bbox = Bnd_Box()
    BRepBndLib_Add(shape, bbox)
    x_min,y_min,z_min,x_max,y_max,z_max = bbox.Get()
    diagonal_length = gp_Vec(gp_Pnt(x_min, y_min, z_min),
                             gp_Pnt(x_max, y_max, z_max)).Magnitude()
    return (diagonal_length / 20.) / quality_factor


[docs]class GeometryWriter(object): """ Tool to convert an OpenCascade shape into a javascript file. :model attributes: .. attribute:: shape :class:`.SimpleShape` that contains the geometry .. attribute:: quality_factor quality of applied to the geometry """ def __init__(self, shape, quality_factor): self.shape = shape self.topo_shape = shape.shape self._precision = get_mesh_precision(self.topo_shape, quality_factor) self.triangle_count = 0 def _triangle_is_valid(self, P1,P2,P3): V1 = gp_Vec(P1,P2) V2 = gp_Vec(P2,P3) V3 = gp_Vec(P3,P1) if V1.SquareMagnitude()>1e-10 and V2.SquareMagnitude()>1e-10 and V3.SquareMagnitude()>1e-10: V1.Cross(V2) if V1.SquareMagnitude()>1e-10: return True else: return False else: return False
[docs] def write_geometries(self, identifier, filename, pov_filename): """ Write the geometry to *filename* (javascript) * and *pov_filename* (POVRay) *identifier* is the name of the generated variable describing the whole geometry. """ opacity = 0.8 directory = os.path.dirname(filename) if not os.path.exists(directory): os.makedirs(directory) shape = self.shape output = open(filename, "w") with open(filename, "w") as output: output.write("//Computation for : %s\n"%shape.name) output.write("var %s = new THREE.Geometry();\n"%identifier) output.write("var material_for%s = new THREE.MeshBasicMaterial({opacity:%s,shading:THREE.SmoothShading});\n"%(identifier,opacity)) with open(pov_filename, "w") as pov_file: pov_file.write(""" #declare m%s = mesh { """ % identifier) if shape.color: output.write("material_for%s.color.setRGB(%f,%f,%f);\n"%(identifier,shape.color.Red(),shape.color.Green(),shape.color.Blue())) self._write_faces(output, pov_file, identifier) if shape.color: color = shape.color.Red(), shape.color.Green(), shape.color.Blue() else: color = 1, 1, 0 pov_file.write(""" }; #declare t%s = texture { pigment { color <%f,%f, %f, 0.9> } finish {ambient 0.1 diffuse 0.9 phong 1} } """ % ((identifier, ) + color))
def _write_faces(self, output, pov_file, identifier): """ Triangulates all faces and writes them to *output* (javascript) and *pov_file* (POVRay). """ BRepMesh_Mesh(self.topo_shape, self._precision) _points = kjDict() faces_iterator = Topo(self.topo_shape).faces() index=0 for F in faces_iterator: face_location = TopLoc_Location() triangulation = BRep_Tool_Triangulation(F,face_location) if triangulation.IsNull() == False: facing = triangulation.GetObject() tab = facing.Nodes() tri = facing.Triangles() the_normal = TColgp_Array1OfDir(tab.Lower(), tab.Upper()) StdPrs_ToolShadedShape_Normal(F, Poly_Connect(facing.GetHandle()), the_normal) for i in range(1, facing.NbTriangles()+1): trian = tri.Value(i) if F.Orientation() == TopAbs_REVERSED: index1, index3, index2 = trian.Get() else: index1, index2, index3 = trian.Get() P1 = tab.Value(index1).Transformed(face_location.Transformation()) P2 = tab.Value(index2).Transformed(face_location.Transformation()) P3 = tab.Value(index3).Transformed(face_location.Transformation()) p1_coord = P1.XYZ().Coord() p2_coord = P2.XYZ().Coord() p3_coord = P3.XYZ().Coord() if self._triangle_is_valid(P1, P2, P3): for point in (p1_coord, p2_coord, p3_coord): if not _points.has_key(point): _points.add(point, index) output.write(vertice_fmt % (identifier, point[0], point[1], point[2])) index+=1 n1 = the_normal(index1) n2 = the_normal(index2) n3 = the_normal(index2) output.write(face_fmt % (identifier, _points.neighbors(p1_coord)[0], _points.neighbors(p2_coord)[0], _points.neighbors(p3_coord)[0], n1.X(), n1.Y(), n1.Z(), n2.X(), n2.Y(), n2.Z(), n3.X(), n3.Y(), n3.Z(), )) pov_file.write(triangle_fmt % ( p1_coord[0], p1_coord[1], p1_coord[2], n1.X(), n1.Y(), n1.Z(), p2_coord[0], p2_coord[1], p2_coord[2], n2.X(), n2.Y(), n2.Z(), p3_coord[0], p3_coord[1], p3_coord[2], n3.X(), n3.Y(), n3.Z(), )) self.triangle_count += 1