From e5ce5c88a439f618d9f330c6883d19dc9654e2da Mon Sep 17 00:00:00 2001
From: Jean-Francois Remacle <jean-francois.remacle@uclouvain.be>
Date: Sun, 16 May 2010 13:20:11 +0000
Subject: [PATCH]

---
 Geo/ACISEdge.cpp               | 151 ++++++++++++++++++++--
 Geo/ACISEdge.h                 |   2 +-
 Geo/ACISFace.cpp               | 223 +++++++++++++++++++++++++++++++++
 Geo/ACISFace.h                 |  48 +++++++
 Geo/ACISVertex.cpp             |   3 +-
 Geo/CMakeLists.txt             |   1 +
 Geo/GModelIO_ACIS.cpp          | 138 ++++++++++++++++++--
 Mesh/meshGFace.cpp             |   4 +-
 benchmarks/boolean/square1.lua |   6 +-
 9 files changed, 551 insertions(+), 25 deletions(-)
 create mode 100644 Geo/ACISFace.cpp
 create mode 100644 Geo/ACISFace.h

diff --git a/Geo/ACISEdge.cpp b/Geo/ACISEdge.cpp
index 9104f1e91e..d21676905f 100644
--- a/Geo/ACISEdge.cpp
+++ b/Geo/ACISEdge.cpp
@@ -8,6 +8,7 @@
 #include "GmshMessage.h"
 #include "GModel.h"
 #include "ACISEdge.h"
+#include "ACISFace.h"
 #include "Context.h"
 
 #if defined(HAVE_ACIS)
@@ -15,6 +16,10 @@
 #include <interval.hxx>
 #include <curve.hxx>
 #include <curdef.hxx>
+#include <intrapi.hxx>
+#include <coedge.hxx>
+#include <loop.hxx>
+#include <surdef.hxx>
 
 GEdge *getACISEdgeByNativePtr(GModel *model, EDGE * toFind)
 {
@@ -34,10 +39,18 @@ GEdge *getACISEdgeByNativePtr(GModel *model, EDGE * toFind)
 ACISEdge::ACISEdge(GModel *model, EDGE* edge, int num, GVertex *v1, GVertex *v2)
   : GEdge(model, num, v1, v2), _e(edge)
 {
-  
-  SPAinterval interval = _e->get_param_range (); 
+  CURVE *_cur = _e->geometry();
+  //  SPAinterval interval=_cur->equation().param_range(); 
+  SPAinterval interval=_e->param_range(); 
   s0 = interval.start_pt();
   s1 = interval.end_pt();
+  if (_cur->equation().periodic()){
+    //    s0 += _cur->equation().param_period()/2;
+    //    s1 += _cur->equation().param_period()/2;
+  }
+  Msg::Info("ACIS Edge %d is %s goes from %g to %g",tag(),getTypeString().c_str(),s0,s1);
+
+
 }
 
 Range<double> ACISEdge::parBounds(int i) const
@@ -47,7 +60,41 @@ Range<double> ACISEdge::parBounds(int i) const
 
 SPoint2 ACISEdge::reparamOnFace(const GFace *face, double epar, int dir) const
 {
-  throw;
+  COEDGE *ce = 0, *firstce = _e->coedge();
+  COEDGE *foundce = 0, *ffoundce=0;
+  int fedir;
+  ce = firstce;
+  
+  int count =0;
+  do {
+    LOOP *l = ce->loop();
+    FACE *f = l->face();
+    count ++;
+    
+    if(f==(FACE*)face->getNativePtr())
+    {
+      fedir = ce->sense()==FORWARD? 1 : 0;
+      if(fedir==dir)
+	foundce = ce;
+      else
+	ffoundce = ce; // save this for later
+    }
+    ce = ce->partner();
+  } while (ce != firstce && !foundce);
+  if(!foundce && ffoundce){
+    foundce = ffoundce;
+    fedir = !fedir;
+  }
+
+  if(!foundce){
+    Msg::Fatal("reparamOnFace - no coedge");
+  }
+  
+  CURVE *c = _e->geometry();
+  SPAposition vpos = c->equation().eval_position(epar);
+  SPApar_pos fpar = ((FACE*)(face->getNativePtr()))->geometry()->equation().param(vpos);
+  SPoint2 pt2(fpar.u, fpar.v);
+  return pt2;
 }
 
 GPoint ACISEdge::closestPoint(const SPoint3 &qp, double &param) const{
@@ -58,9 +105,75 @@ GPoint ACISEdge::closestPoint(const SPoint3 &qp, double &param) const{
 // True if the edge is a seam for the given face
 bool ACISEdge::isSeam(const GFace *face) const
 {
-  throw;
+  //  return false;
+  CURVE *_cur = _e->geometry();
+  if (!(((FACE*)face->getNativePtr())->geometry()->equation().periodic_u()) && 
+      !(((FACE*)face->getNativePtr())->geometry()->equation().periodic_u()))
+      return 0;
+  else if ( (((FACE*)face->getNativePtr())->geometry()->equation().periodic_u()) && 
+           !(((FACE*)face->getNativePtr())->geometry()->equation().periodic_u()))
+  {
+     SPAinterval cur_rang = _cur->equation().param_range();
+     SPAinterval sur_rang_u = ((FACE*)face->getNativePtr())->geometry()->equation().param_range_u();
+     SPAposition p1, p2;
+     p1 = _cur->equation().eval_position(cur_rang.start_pt());
+     p2 = _cur->equation().eval_position(cur_rang.end_pt());
+     SPApar_pos p1_par, p2_par;
+     p1_par = ((FACE*)face->getNativePtr())->geometry()->equation().param(p1);
+     p2_par = ((FACE*)face->getNativePtr())->geometry()->equation().param(p2);
+  
+    if(((p1_par.u == sur_rang_u.start_pt()  || p1_par.u == sur_rang_u.end_pt()) && 
+        (p2_par.u == sur_rang_u.start_pt()  || p2_par.u == sur_rang_u.end_pt())))
+        return 1;
+     else
+        return 0;
+  }
+  else if (!(((FACE*)face->getNativePtr())->geometry()->equation().periodic_u()) && 
+            (((FACE*)face->getNativePtr())->geometry()->equation().periodic_u()))
+  {
+     SPAinterval cur_rang = _cur->equation().param_range();
+     SPAinterval sur_rang_v = ((FACE*)face->getNativePtr())->geometry()->equation().param_range_v();
+     SPAposition p1, p2;
+     p1 = _cur->equation().eval_position(cur_rang.start_pt());
+     p2 = _cur->equation().eval_position(cur_rang.end_pt());
+     SPApar_pos p1_par, p2_par;
+     p1_par = ((FACE*)face->getNativePtr())->geometry()->equation().param(p1);
+     p2_par = ((FACE*)face->getNativePtr())->geometry()->equation().param(p2);
+  
+    if(((p1_par.v == sur_rang_v.start_pt()  || p1_par.v == sur_rang_v.end_pt()) && 
+        (p2_par.v == sur_rang_v.start_pt()  || p2_par.v == sur_rang_v.end_pt())) )
+        return 1;
+     else
+        return 0;
+  }
+  else if ((((FACE*)face->getNativePtr())->geometry()->equation().periodic_u()) && 
+           (((FACE*)face->getNativePtr())->geometry()->equation().periodic_u()))
+  {
+     SPAinterval cur_rang = _cur->equation().param_range();
+     SPAinterval sur_rang_u = ((FACE*)face->getNativePtr())->geometry()->equation().param_range_u();
+     SPAinterval sur_rang_v = ((FACE*)face->getNativePtr())->geometry()->equation().param_range_v();
+     SPAposition p1, p2;
+     p1 = _cur->equation().eval_position(cur_rang.start_pt());
+     p2 = _cur->equation().eval_position(cur_rang.end_pt());
+     SPApar_pos p1_par, p2_par;
+     p1_par = ((FACE*)face->getNativePtr())->geometry()->equation().param(p1);
+     p2_par = ((FACE*)face->getNativePtr())->geometry()->equation().param(p2);
+  
+     if ( ((p1_par.u == sur_rang_u.start_pt()  || p1_par.u == sur_rang_u.end_pt()) && 
+        (p2_par.u == sur_rang_u.start_pt()  || p2_par.u == sur_rang_u.end_pt())) ||
+       ((p1_par.v == sur_rang_v.start_pt()  || p1_par.v == sur_rang_v.end_pt()) && 
+        (p2_par.v == sur_rang_v.start_pt()  || p2_par.v == sur_rang_v.end_pt())) )
+        return 1;
+     else
+        return 0;
+  }
+}
+
+bool ACISEdge::degenerate(int) const{
+  return _e->length() == 0.0;
 }
 
+
 GPoint ACISEdge::point(double par) const
 {
   CURVE *c = _e->geometry();
@@ -76,22 +189,46 @@ GPoint ACISEdge::point(double par) const
 
 SVector3 ACISEdge::firstDer(double par) const
 {  
-  return SVector3(0,0,0);
+  CURVE *c = _e->geometry();
+  const curve &equ = c->equation();
+  SPAvector first_deriv;
+  SPAposition pos;
+  equ.eval (par, pos,first_deriv);
+  return SVector3(first_deriv.component(0),first_deriv.component(1),first_deriv.component(2));
 }
 
 GEntity::GeomType ACISEdge::geomType() const
 {
+  CURVE *c = _e->geometry();
+  if (!strcmp(c->type_name(),"circle"))return Circle;
+  if (!strcmp(c->type_name(),"straight"))return Line;
+  if (!strcmp(c->type_name(),"ellipse"))return Ellipse;
+  if (!strcmp(c->type_name(),"bezier"))return Bezier;
   return Unknown;
 }
 
 int ACISEdge::minimumMeshSegments() const
 {
-  return GEdge::minimumMeshSegments();
+  int np;
+  if(geomType() == Line)
+    np = GEdge::minimumMeshSegments();
+  else 
+    np = CTX::instance()->mesh.minCurvPoints - 1;
+  
+  // if the edge is closed, ensure that at least 3 points are
+  // generated in the 1D mesh (4 segments, one of which is
+  // degenerated)
+  if (getBeginVertex() == getEndVertex()) np = std::max(4, np);
+
+  return std::max(np, meshAttributes.minimumMeshSegments);
 }
 
 int ACISEdge::minimumDrawSegments() const
 {
-  return GEdge::minimumDrawSegments();
+  if(geomType() == Line)
+    return GEdge::minimumDrawSegments();
+  else
+    return CTX::instance()->geom.numSubEdges * GEdge::minimumDrawSegments();
 }
 
 double ACISEdge::curvature(double par) const 
diff --git a/Geo/ACISEdge.h b/Geo/ACISEdge.h
index ff36fc7808..ed06a5683a 100644
--- a/Geo/ACISEdge.h
+++ b/Geo/ACISEdge.h
@@ -27,7 +27,7 @@ class ACISEdge : public GEdge {
   virtual ~ACISEdge() {}
   virtual Range<double> parBounds(int i) const;
   virtual GeomType geomType() const;
-  virtual bool degenerate(int) const { return false; }
+  virtual bool degenerate(int) const;
   virtual GPoint point(double p) const;
   virtual SVector3 firstDer(double par) const;
   virtual double curvature (double par) const;
diff --git a/Geo/ACISFace.cpp b/Geo/ACISFace.cpp
new file mode 100644
index 0000000000..40856964e1
--- /dev/null
+++ b/Geo/ACISFace.cpp
@@ -0,0 +1,223 @@
+// Gmsh - Copyright (C) 1997-2010 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#include "GmshConfig.h"
+#include "GmshMessage.h"
+#include "GModel.h"
+#include "GEdgeLoop.h"
+#include "ACISVertex.h"
+#include "ACISEdge.h"
+#include "ACISFace.h"
+#include "Numeric.h"
+#include "Context.h"
+
+#if defined(HAVE_ACIS)
+
+#include <loop.hxx>
+#include <surdef.hxx>
+#include <coedge.hxx>
+#include <intrapi.hxx>
+#include <poly_vtx.hxx>
+#include <api.hxx>
+#include <kernapi.hxx>
+#include <af_api.hxx>
+
+ACISFace::ACISFace(GModel *m, FACE *f, int num)
+  : GFace(m, num), _f(f)
+{
+  edgeLoops.clear();
+  l_edges.clear();
+  l_dirs.clear();
+  
+  LOOP *myLoop = _f->loop();
+  do{
+    std::list<GEdge*> l_wire;
+    COEDGE *start = myLoop->start();
+    COEDGE *_current  = start;
+    do {
+      EDGE *e = _current->edge();
+      GEdge *ge = getACISEdgeByNativePtr(m,e);
+      l_wire.push_back(ge);      
+      _current = _current->next();
+    }while (_current && _current != start);
+    GEdgeLoop el(l_wire);
+    for(GEdgeLoop::citer it = el.begin(); it != el.end(); ++it){
+      l_edges.push_back(it->ge);
+      l_dirs.push_back(it->_sign);
+      if (el.count() == 2){
+        it->ge->meshAttributes.minimumMeshSegments = 
+          std::max(it->ge->meshAttributes.minimumMeshSegments,2);
+      }
+      if (el.count() == 1){
+        it->ge->meshAttributes.minimumMeshSegments = 
+          std::max(it->ge->meshAttributes.minimumMeshSegments,3);
+      }
+    }
+    edgeLoops.push_back(el);   
+  }while (myLoop = myLoop->next());
+
+  SURFACE *Surf = _f->geometry();
+  const surface &surf = Surf->equation();
+
+  SPAinterval _u,_v;
+  _u = surf.param_range_u();
+  _v = surf.param_range_v();
+
+  umin = _u.start_pt();
+  umax = _u.end_pt();
+
+  vmin = _v.start_pt();
+  vmax = _v.end_pt();
+
+
+  if ( surf.closed_u() || surf.closed_v() ) {
+    printf("%d %g %g -- %g %g\n",tag(),umin,umax,vmin,vmax);
+  }
+
+
+  _periodic[0] = surf.periodic_u();
+  _periodic[1] = surf.periodic_v();
+
+  const double du = umax - umin;
+  const double dv = vmax - vmin;
+  umin -= fabs(du) / 100.0;
+  vmin -= fabs(dv) / 100.0;
+  umax += fabs(du) / 100.0;
+  vmax += fabs(dv) / 100.0;
+}
+
+Range<double> ACISFace::parBounds(int i) const
+{  
+  if(i == 0)
+    return Range<double>(umin, umax);
+  return Range<double>(vmin, vmax);
+}
+
+SVector3 ACISFace::normal(const SPoint2 &param) const
+{
+
+  SURFACE *Surf = _f->geometry();
+  const surface &surf = Surf->equation();
+
+  const SPAunit_vector n = surf.eval_normal (SPApar_pos (param.x(),param.y()));  
+  return SVector3(n.component(0),n.component(1),n.component(2));  
+}
+
+Pair<SVector3,SVector3> ACISFace::firstDer(const SPoint2 &param) const
+{
+  SURFACE *Surf = _f->geometry();
+  const surface &surf = Surf->equation();
+  SPAposition pos;
+  SPAvector first_derivs[2];
+  surf.eval (SPApar_pos(param.x(),param.y()), pos,first_derivs);
+  return Pair<SVector3,SVector3> (
+				  SVector3(first_derivs[0].component(0),first_derivs[0].component(1),first_derivs[0].component(2)),
+				  SVector3(first_derivs[1].component(0),first_derivs[1].component(1),first_derivs[1].component(2))
+				  );
+}
+
+void ACISFace::secondDer(const SPoint2 &param,
+                        SVector3 *dudu, SVector3 *dvdv, SVector3 *dudv) const
+{
+  SURFACE *Surf = _f->geometry();
+  const surface &surf = Surf->equation();
+}
+
+GPoint ACISFace::point(double par1, double par2) const
+{
+  SURFACE *Surf = _f->geometry();
+  const surface &surf = Surf->equation();
+  SPAposition pos;
+  surf.eval (SPApar_pos(par1,par2), pos);
+  double pp[2] = {par1,par2};
+  return GPoint(pos.coordinate(0),pos.coordinate(1),pos.coordinate(2),this,pp);    
+}
+
+GPoint ACISFace::closestPoint(const SPoint3 &qp, const double initialGuess[2]) const
+{
+  SPAposition pt(qp.x(),qp.y(),qp.z());
+  SPAposition fpt;
+  SPApar_pos ppt;
+  SURFACE *Surf = _f->geometry();
+
+  Surf->equation().point_perp(pt,fpt,*(SPApar_pos *)NULL_REF,ppt);
+  SPoint2 pt2(ppt.u,ppt.v);	
+
+  return GPoint(fpt.x(),fpt.y(),fpt.z(),this,pt2);
+}
+
+SPoint2 ACISFace::parFromPoint(const SPoint3 &qp) const
+{
+  SURFACE *Surf = _f->geometry();
+  SPAposition pt(qp.x(),qp.y(),qp.z());
+  SPApar_pos ppt = Surf->equation().param(pt);
+   
+  SPoint2 pt2(ppt.u,ppt.v);	// 200306
+
+  GPoint sp = point(ppt.u,ppt.v);
+  //  printf("%g %g %g vs %g %g %g\n",qp.x(),qp.y(),qp.z(),sp.x(),sp.y(),sp.z());
+
+  return pt2;
+}
+
+GEntity::GeomType ACISFace::geomType() const
+{
+  SURFACE *Surf = _f->geometry();
+  if (!strcmp(Surf->type_name(),"plane"))return Plane;
+  if (!strcmp(Surf->type_name(),"sphere"))return Sphere;
+  if (!strcmp(Surf->type_name(),"cone"))return Cone;
+  if (!strcmp(Surf->type_name(),"torus"))return Torus;
+  if (!strcmp(Surf->type_name(),"cylinder"))return Cylinder;
+  return Unknown;
+}
+
+double ACISFace::curvatureMax(const SPoint2 &param) const
+{
+  return 1.e22;
+}
+
+double ACISFace::curvatures(const SPoint2 &param,
+                           SVector3 *dirMax,
+                           SVector3 *dirMin,
+                           double *curvMax,
+                           double *curvMin) const
+{
+  return 1.e22;
+}
+
+bool ACISFace::containsPoint(const SPoint3 &pt) const
+{ 
+  return false;
+}
+
+bool ACISFace::buildSTLTriangulation(bool force)
+{
+  if(stl_triangles.size()){
+    if(force){
+      stl_vertices.clear();
+      stl_triangles.clear();
+    }
+    else
+      return true;
+  }
+  outcome out = api_facet_entity(_f);
+  if (!out.ok())return false;
+  return true;
+}
+
+GFace *getACISFaceByNativePtr(GModel *model, FACE *f)
+{
+  GModel::fiter it =model->firstFace();
+  for (; it !=model->lastFace(); ++it){
+    ACISFace *gf = dynamic_cast<ACISFace*>(*it);
+    if (gf){
+      if (f == (FACE*)gf->getNativePtr())return gf;
+    }
+  }
+  return 0;
+}
+
+
+#endif
diff --git a/Geo/ACISFace.h b/Geo/ACISFace.h
new file mode 100644
index 0000000000..c2a041553c
--- /dev/null
+++ b/Geo/ACISFace.h
@@ -0,0 +1,48 @@
+// Gmsh - Copyright (C) 1997-2010 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _ACIS_FACE_H_
+#define _ACIS_FACE_H_
+
+#include "GmshConfig.h"
+#include "GFace.h"
+#include "GModel.h"
+#include "ACISVertex.h"
+#include "ACISEdge.h"
+#include "Range.h"
+
+#if defined(HAVE_ACIS)
+#include <face.hxx>
+#include <surface.hxx>
+class ACISFace : public GFace {
+ protected:
+  FACE *_f;
+  double umin, umax, vmin, vmax;
+  bool _periodic[2];
+ public:
+  ACISFace(GModel *m, FACE *f, int num);
+  virtual ~ACISFace(){}
+  Range<double> parBounds(int i) const; 
+  virtual GPoint point(double par1, double par2) const; 
+  virtual GPoint closestPoint(const SPoint3 & queryPoint, const double initialGuess[2]) const; 
+  virtual bool containsPoint(const SPoint3 &pt) const;  
+  virtual SVector3 normal(const SPoint2 &param) const; 
+  virtual Pair<SVector3,SVector3> firstDer(const SPoint2 &param) const;
+  virtual void secondDer(const SPoint2 &, SVector3 *, SVector3 *, SVector3 *) const;
+  virtual GEntity::GeomType geomType() const; 
+  ModelType getNativeType() const { return AcisModel; }
+  void *getNativePtr() const { return (void*)_f; }
+  virtual SPoint2 parFromPoint(const SPoint3 &) const;
+  virtual double curvatureMax(const SPoint2 &param) const;
+  virtual double curvatures(const SPoint2 &param, SVector3 *dirMax, SVector3 *dirMin,
+                            double *curvMax, double *curvMin) const;
+  bool buildSTLTriangulation(bool force);
+  FACE* getFACE () {return _f;}
+};
+GFace *getACISFaceByNativePtr(GModel *model, FACE *);
+
+#endif
+
+#endif
diff --git a/Geo/ACISVertex.cpp b/Geo/ACISVertex.cpp
index 8699be4be3..3c902d13ca 100644
--- a/Geo/ACISVertex.cpp
+++ b/Geo/ACISVertex.cpp
@@ -33,7 +33,8 @@ void ACISVertex::setPosition(GPoint &p)
 
 SPoint2 ACISVertex::reparamOnFace(const GFace *gf, int dir) const
 {
-  Msg::Fatal("NOT DONE !!!!!!!!!!!\n");
+  // FIXME there is definitively a fastest way to do it and this is wring for seams и!!!
+  return gf->parFromPoint(SPoint3(x(),y(),z()));
 }
 
 GVertex *getACISVertexByNativePtr(GModel *model, VERTEX* toFind)
diff --git a/Geo/CMakeLists.txt b/Geo/CMakeLists.txt
index e7e4ff7b65..70310e4ae6 100644
--- a/Geo/CMakeLists.txt
+++ b/Geo/CMakeLists.txt
@@ -13,6 +13,7 @@ set(SRC
     fourierEdge.cpp fourierFace.cpp fourierProjectionFace.cpp
   ACISVertex.cpp
   ACISEdge.cpp
+  ACISFace.cpp
   GModel.cpp
   GModelFactory.cpp
     GModelIO_Geo.cpp
diff --git a/Geo/GModelIO_ACIS.cpp b/Geo/GModelIO_ACIS.cpp
index 3c0421bed4..40ac6462b0 100644
--- a/Geo/GModelIO_ACIS.cpp
+++ b/Geo/GModelIO_ACIS.cpp
@@ -9,9 +9,11 @@
 #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>
@@ -22,19 +24,100 @@
 #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){
+  }
+  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)pnode;
+}
+
+
 
 class ACIS_Internals {
 public:
   ENTITY_LIST entities;
-  ACIS_Internals();
+  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);
+  void addFaces(GModel *gm, ENTITY_LIST &l);
 };
 
-ACIS_Internals::ACIS_Internals()
+ACIS_Internals::ACIS_Internals(GModel *gm)
 {
   // put your acis unlock string here...
 #include "ACISLICENSE.h"
@@ -44,6 +127,33 @@ ACIS_Internals::ACIS_Internals()
   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()
@@ -52,6 +162,7 @@ ACIS_Internals::~ACIS_Internals()
   if (!prout.ok()){
     Msg::Error("Unable to stop ACIS");
   }  
+  delete _mm;
 }
 
 void ACIS_Internals::addVertices (GModel *gm, ENTITY_LIST &l)
@@ -85,7 +196,7 @@ void ACIS_Internals::addEdges (GModel *gm, ENTITY_LIST &l)
   }
 }
 
-/*
+
 void ACIS_Internals::addFaces (GModel *gm, ENTITY_LIST &l)
 {
   l.init();
@@ -95,14 +206,12 @@ void ACIS_Internals::addFaces (GModel *gm, ENTITY_LIST &l)
     if (av){
       GFace *v = getACISFaceByNativePtr(gm,av);
       if (!v){
-	GVertex *v1 = getACISVertexByNativePtr(gm,av->start());
-	GVertex *v2 = getACISVertexByNativePtr(gm,av->end());      
-	gm->add(new ACISEdge(gm,av,gm->maxEdgeNum()+1,v1,v2));
+	gm->add(new ACISFace(gm,av,gm->maxFaceNum()+1));
       }
     }
   }
 }
-*/
+
 
 void ACIS_Internals::loadSAT(std::string fileName, GModel *gm)
 {
@@ -120,11 +229,12 @@ void ACIS_Internals::loadSAT(std::string fileName, GModel *gm)
   ENTITY *e;
   entities.init();
   while(e = entities.next()){
-    printf("an entity\n");
+    //    printf("an entity\n");
     if (is_VERTEX(e)){
-      printf("VERTEX FOUND\n");
+      //      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);
@@ -137,13 +247,19 @@ void ACIS_Internals::loadSAT(std::string fileName, GModel *gm)
 	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;
+  _acis_internals = new ACIS_Internals(this);
   _acis_internals->loadSAT(fn,this);
   return 1;
 }
diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp
index c52bfc95eb..d9aaa7256e 100644
--- a/Mesh/meshGFace.cpp
+++ b/Mesh/meshGFace.cpp
@@ -1332,7 +1332,7 @@ void deMeshGFace::operator() (GFace *gf)
   gf->meshStatistics.nbTriangle = gf->meshStatistics.nbEdge = 0;
 }
 
-int debugSurface = -1;
+int debugSurface = -100;
 
 void meshGFace::operator() (GFace *gf)
 {
@@ -1390,7 +1390,7 @@ void meshGFace::operator() (GFace *gf)
     meshGenerator(gf, 0, repairSelfIntersecting1dMesh,
                   debugSurface >= 0 || debugSurface == -100);
   }
-  else{
+  else {
     if(!meshGeneratorPeriodic
        (gf, debugSurface >= 0 || debugSurface == -100))
       Msg::Error("Impossible to mesh face %d", gf->tag());
diff --git a/benchmarks/boolean/square1.lua b/benchmarks/boolean/square1.lua
index a5a277a971..a39d40f776 100644
--- a/benchmarks/boolean/square1.lua
+++ b/benchmarks/boolean/square1.lua
@@ -9,9 +9,9 @@ e2 = g:addLine(v2, v3)
 e3 = g:addLine(v3, v4)
 e4 = g:addLine(v4, v1)
 v11 = g:addVertex(.4, .4, 0, .1)
-v12 = g:addVertex(.5, .4, 0, .1)
-v13 = g:addVertex(.5, .5, 0, .1)
-v14 = g:addVertex(.4, .5, 0, .1)
+v12 = g:addVertex(.6, .4, 0, .1)
+v13 = g:addVertex(.6, .5, 0, .1)
+v14 = g:addVertex(.4, .6, 0, .1)
 e11 = g:addLine(v11, v12)
 e12 = g:addLine(v12, v13)
 e13 = g:addLine(v13, v14)
-- 
GitLab