// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle // // See the LICENSE.txt file for license information. Please report all // bugs and problems to the public mailing list <gmsh@onelab.info>. #include "GmshConfig.h" #include "GModel.h" #include "GmshMessage.h" #include "OS.h" #include "GModelIO_ACIS.h" #include "ACISVertex.h" #include "ACISEdge.h" #include "ACISFace.h" #if defined(HAVE_ACIS) #include <meshmg.hxx> #include <acis.hxx> #include <base.hxx> #include <license.hxx> #include <spa_unlock_result.hxx> #include <spa_lic_err_gui.hxx> #include <api.hxx> #include <kernapi.hxx> #include <mmgr.err> #include <lists.hxx> #include <acistype.hxx> #include "acis.hxx" #include "kernapi.hxx" #include "boolapi.hxx" #include "eulerapi.hxx" #include "cstrapi.hxx" #include "af_api.hxx" #include "intrapi.hxx" #include "ga_api.hxx" #include "spl_api.hxx" class GMSH_MESH_MANAGER : public MESH_MANAGER { GModel *_gm; GFace *_current; public: GMSH_MESH_MANAGER(GModel *gm) : _gm(gm) { } virtual ~GMSH_MESH_MANAGER() { } virtual void begin_mesh_output(ENTITY *entity, ENTITY *app_ref, ENTITY *format) { FACE *acisFace = dynamic_cast<FACE*>(entity); if (!acisFace) return; _current = getACISFaceByNativePtr (_gm,acisFace); } virtual void announce_counts(int npoly, int nnode, int nref) { _current->stl_vertices.resize(nnode); _current->stl_triangles.resize(nref); } virtual logical need_indexed_polygons() { return 1; } virtual void announce_indexed_polynode(int ipoly, int i, void *pnode); virtual void *announce_indexed_node(int inode, const SPApar_pos &pos, const SPAposition &X, const SPAunit_vector &N) { SPoint2 p(pos.u,pos.v); _current->stl_vertices[inode] = p; // printf("node %d pos %g %g\n",inode,p.x(),p.y()); return (void*)inode; // bad idea, but... } virtual void announce_indexed_polynode(ENTITY *E, int ipoly, int i, void *id, const double &edge_tpar, const SPApar_pos &uv, const SPAposition &iX, const SPAunit_vector &N) { } virtual void *announce_indexed_polyedge(int ipoly, int i, void *mate) { return 0; } virtual void start_indexed_polygon(int polygonIndex,int _polygonNodeCount, int ishare = -2) { } virtual void announce_indexed_polynode(ENTITY *,int,int,void*) { } virtual void end_mesh_output(ENTITY *entity, ENTITY *app_ref,ENTITY *format) { } virtual void save_mesh_output(ENTITY *entity,ENTITY *app_ref,ENTITY *format) { } }; void GMSH_MESH_MANAGER::announce_indexed_polynode (int ipoly, int i, void *pnode) { _current->stl_triangles[ipoly*3+i] = (int)(long)pnode; } class ACIS_Internals { public: ENTITY_LIST entities; GMSH_MESH_MANAGER *_mm; ACIS_Internals(GModel *gm); ~ACIS_Internals(); void loadSAT(std::string fileName, GModel*); void addVertices(GModel *gm, ENTITY_LIST &l); void addEdges(GModel *gm, ENTITY_LIST &l); void addFaces(GModel *gm, ENTITY_LIST &l); }; ACIS_Internals::ACIS_Internals(GModel *gm) { // put your acis unlock string here... #include "ACISLICENSE.h" spa_unlock_result out = spa_unlock_products(unlock_str); outcome prout = api_start_modeller(0); if (!prout.ok()){ Msg::Error("Unable to start ACIS"); } option_header* seam_option = NULL; seam_option = find_option("periodic_no_seam"); if (seam_option != NULL) seam_option->push(FALSE); api_initialize_booleans(); api_initialize_euler_ops(); api_initialize_constructors(); api_initialize_intersectors(); api_initialize_generic_attributes(); api_initialize_kernel(); api_initialize_spline(); api_initialize_faceter(); _mm = new GMSH_MESH_MANAGER(gm); api_set_mesh_manager(_mm); /* REFINEMENT *ref = new REFINEMENT; ref->set_surf_mode(AF_SURF_ALL); ref->set_normal_tol(60); // 30 ref->set_surface_tol(0.1); // 0.05 ref->set_grid_mode(AF_GRID_TO_EDGES); ref->set_triang_mode(AF_TRIANG_ALL ); api_set_default_refinement(ref); */ } ACIS_Internals::~ACIS_Internals() { outcome prout = api_stop_modeller(); if (!prout.ok()){ Msg::Error("Unable to stop ACIS"); } delete _mm; } void ACIS_Internals::addVertices (GModel *gm, ENTITY_LIST &l) { l.init(); ENTITY *e; while((e = l.next())){ VERTEX *av = dynamic_cast<VERTEX*>(e); if (av){ GVertex *v = getACISVertexByNativePtr(gm, av); if (!v) gm->add(new ACISVertex (gm, gm->getMaxElementaryNumber(0) + 1, av)); } } } void ACIS_Internals::addEdges (GModel *gm, ENTITY_LIST &l) { l.init(); ENTITY *e; while((e = l.next())){ EDGE *av = dynamic_cast<EDGE*>(e); if (av){ GEdge *v = getACISEdgeByNativePtr(gm, av); if (!v){ GVertex *v1 = getACISVertexByNativePtr(gm, av->start()); GVertex *v2 = getACISVertexByNativePtr(gm, av->end()); gm->add(new ACISEdge(gm, av, gm->getMaxElementaryNumber(1) + 1, v1, v2)); } } } } void ACIS_Internals::addFaces (GModel *gm, ENTITY_LIST &l) { l.init(); ENTITY *e; while((e = l.next())){ FACE *av = dynamic_cast<FACE*>(e); if (av){ GFace *v = getACISFaceByNativePtr(gm,av); if (!v){ gm->add(new ACISFace(gm, av, gm->getMaxElementaryNumber(2) + 1)); } } } } void ACIS_Internals::loadSAT(std::string fileName, GModel *gm) { FILE *f = Fopen (fileName.c_str(), "r"); if (!f){ return; } outcome prout = api_restore_entity_list(f,1,entities); if (!prout.ok()){ Msg::Error("Unable to load ACIS FILE %d",fileName.c_str()); fclose(f); return; } Msg::Info("ACIS FILE %d Loaded",fileName.c_str()); ENTITY *e; entities.init(); while((e = entities.next())){ // printf("an entity\n"); if (is_VERTEX(e)){ // printf("VERTEX FOUND\n"); } if (is_BODY(e)){ api_split_periodic_faces(e); { ENTITY_LIST vertex_list; outcome prout = api_get_vertices (e,vertex_list); addVertices (gm,vertex_list); printf("BODY COUNT %d !\n",vertex_list.count()); } { ENTITY_LIST edge_list; outcome prout = api_get_edges (e,edge_list); addEdges (gm,edge_list); printf("BODY COUNT %d !\n",edge_list.count()); } { ENTITY_LIST face_list; outcome prout = api_get_faces(e,face_list); addFaces (gm,face_list); printf("BODY COUNT %d !\n",face_list.count()); } } } } int GModel::readACISSAT(const std::string &fn) { _acis_internals = new ACIS_Internals(this); _acis_internals->loadSAT(fn,this); return 1; } #else int GModel::readACISSAT(const std::string &fn) { Msg::Error("Gmsh must be compiled with ACIS support to load '%s'", fn.c_str()); return 0; } #endif