diff --git a/Geo/FEdge.cpp b/Geo/FEdge.cpp
index d164625492c1a2cb72d8b2e8cd42f25782b93a59..422287583a777927b9bcd0820261ae8456522b35 100644
--- a/Geo/FEdge.cpp
+++ b/Geo/FEdge.cpp
@@ -70,4 +70,35 @@ double FEdge::parFromPoint(const SPoint3 &pt) const
   return p;
 }
 
+SVector3 FEdge::firstDer(double par) const
+{
+  double x,y,z;
+  if (edge)
+    edge->Dfdt(par,x,y,z);
+  else {
+    x = y = z = 0.;
+  }
+  return SVector3(x,y,z);
+}
+
+int FEdge::minimumMeshSegments() const
+{
+  if(geomType() == Line || geomType() == Unknown)
+    return GEdge::minimumMeshSegments();
+  else
+    return 2; // always put at least one mid-point on non-straight lines
+}
+
+int FEdge::minimumDrawSegments() const
+{
+  int n = GEdge::minimumDrawSegments();
+
+  if(geomType() == Line)
+    return n;
+  else if(geomType() == Circle || geomType() == Ellipse)
+    return CTX.geom.circle_points;
+  else
+    return 20 * n;
+}
+
 #endif
diff --git a/Geo/FEdge.h b/Geo/FEdge.h
index ce08ccdd274c3e8f8be874e737391041ce6fa0c2..e23dc3d608053b4b6bf6c1e04aa815d31f7aee9e 100644
--- a/Geo/FEdge.h
+++ b/Geo/FEdge.h
@@ -5,6 +5,7 @@
 #include "GModel.h"
 #include "FVertex.h"
 #include "Range.h"
+#include "Message.h"
 
 #if defined(HAVE_FOURIER_MODEL)
 
@@ -26,19 +27,18 @@ class FEdge : public GEdge {
   double period() const { throw ; }
   virtual bool periodic(int dim=0) const { return false; }
   virtual Range<double> parBounds(int i) const;
-  virtual GeomType geomType() const { throw; }
+  virtual GeomType geomType() const { return ParametricCurve; }
   virtual bool degenerate(int) const { return false; }
   virtual bool continuous(int dim) const { return true; }
   virtual GPoint point(double p) const;
   virtual GPoint closestPoint(const SPoint3 & queryPoint) { throw; }
   virtual int containsPoint(const SPoint3 &pt) const { throw; }
   virtual int containsParam(double pt) const { throw; }
-  virtual SVector3 firstDer(double par) const { throw; }
-  virtual SPoint2 reparamOnFace(GFace *face, double epar, int dir) const 
-  { throw; }
+  virtual SVector3 firstDer(double par) const;
+  //virtual SPoint2 reparamOnFace(GFace *face, double epar, int dir) const;
   virtual double parFromPoint(const SPoint3 &pt) const;
-  virtual int minimumMeshSegments () const { throw; }
-  virtual int minimumDrawSegments () const { throw; }
+  virtual int minimumMeshSegments () const;
+  virtual int minimumDrawSegments () const;
   ModelType getNativeType() const { return FourierModel; }
 };
 
diff --git a/Geo/FFace.cpp b/Geo/FFace.cpp
index 406675a75ad719b959c2717a10fac6ff2ae45f99..5040ad75c0a7a9a97a6d5eebabf4cb67d6d933e5 100644
--- a/Geo/FFace.cpp
+++ b/Geo/FFace.cpp
@@ -5,52 +5,13 @@
 
 #if defined(HAVE_FOURIER_MODEL)
 
-FFace::FFace(GModel *m, FM_Face *face_, int tag) : GFace(m,tag), face(face_) 
+FFace::FFace(GModel *m, FM_Face *face_, int tag, std::list<GEdge*> l_edges_) 
+  : GFace(m,tag), face(face_)
 {
-  if (face->GetNumEdges()) {
-    std::list<GVertex*> corners;
-    std::list<GVertex*>::iterator itStart, itEnd;
-
-    corners.push_back(new FVertex(m,0,face->GetEdge(0)->
-				  GetStartPoint()));
-    corners.push_back(new FVertex(m,1,face->GetEdge(1)->
-				  GetStartPoint()));
-    corners.push_back(new FVertex(m,2,face->GetEdge(2)->
-				  GetStartPoint()));
-    corners.push_back(new FVertex(m,3,face->GetEdge(3)->
-				  GetStartPoint()));
-
-    itStart = itEnd = corners.begin(); itEnd++;
-    for (int i=0;i<face->GetNumEdges();i++) {
-      l_edges.push_back(new FEdge(m,face->GetEdge(i),i,*itStart,*itEnd));
-      l_dirs.push_back(1);      
-      itStart++; itEnd++;
-      if (itEnd == corners.end()) {
-	itEnd = corners.begin();
-      }
-    }
-    for (std::list<GEdge*>::iterator it = l_edges.begin();it != l_edges.end();
-	 it++) {
-      GVertex *start = (*it)->getBeginVertex();
-      GVertex *end = (*it)->getEndVertex();
-      Msg(INFO,"(%g,%g,%g) --- (%g,%g,%g)",start->x(),start->y(),start->z(),
-	  end->x(),end->y(),end->z());
-    }
-  }
-  else {
-    double x,y,z;
-    face->F(0.,0.,x,y,z);
-    GVertex* p0 = new FVertex(m,0,new FM_Vertex(x,y,z));
-    face->F(1.,0.,x,y,z);
-    GVertex* p1 = new FVertex(m,1,new FM_Vertex(x,y,z));
-    face->F(1.,1.,x,y,z);
-    GVertex* p2 = new FVertex(m,2,new FM_Vertex(x,y,z));
-    face->F(0.,1.,x,y,z);
-    GVertex* p3 = new FVertex(m,3,new FM_Vertex(x,y,z));
-    l_edges.push_back(new FEdge(m,face,0,0,p0,p1));
-    l_edges.push_back(new FEdge(m,face,1,1,p1,p2));
-    l_edges.push_back(new FEdge(m,face,2,2,p2,p3));
-    l_edges.push_back(new FEdge(m,face,3,3,p3,p0));
+  for (std::list<GEdge*>::iterator it = l_edges_.begin();
+       it != l_edges_.end(); it++) {
+    l_edges.push_back((*it));
+    l_dirs.push_back(1);   
   }
 }
 
diff --git a/Geo/FFace.h b/Geo/FFace.h
index 5c6bb11b8f9347aa2b18e94a2ff44e4d16e409fa..fcdf396c077f76c5f7aaa2ecc60427feb84b7a8d 100644
--- a/Geo/FFace.h
+++ b/Geo/FFace.h
@@ -15,7 +15,7 @@ class FFace : public GFace {
   FM_Face *face;
   bool _periodic[2];
  public:
-  FFace(GModel *m, FM_Face *face_, int tag);
+  FFace(GModel *m, FM_Face *face_, int tag, std::list<GEdge*> l_edges_);
 
   virtual ~FFace() {}
 
diff --git a/Geo/GModel.h b/Geo/GModel.h
index 20487dd47509706f34f26a4a824742c27c6509e2..2b5072101345969579c5dda7c3b439b8ef044d2c 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -32,6 +32,8 @@
 
 // OCC Internals have to be stored in the model
 class OCC_Internals;
+// Fourier Internals have to be stored in the model
+class F_Internals;
 
 // A geometric model. The model is a "not yet" non-manifold B-Rep.
 class GModel  
@@ -39,6 +41,7 @@ class GModel
  private:
   void deleteOCCInternals();
   OCC_Internals *occ_internals;
+  F_Internals *f_internals;
 
  protected:
   std::string modelName;
diff --git a/Geo/GModelIO_F.cpp b/Geo/GModelIO_F.cpp
index c621df437aa3f33eb5305e21ced0edc498d74350..97a7322ac38d33e7ffc2e5a125c24b72fbb4c0d3 100644
--- a/Geo/GModelIO_F.cpp
+++ b/Geo/GModelIO_F.cpp
@@ -5,23 +5,55 @@
 #include "Views.h"
 #include "FFace.h"
 #include "meshGFace.h" 
+#include "GModelIO_F.h"
 
 #if defined(HAVE_FOURIER_MODEL)
 
-#include "FM_Reader.h"
-
 extern Context_T CTX;
 
-int GModel::readF(const std::string &fn)
+void F_Internals::loadF(const char *fn)
 {
-  CTX.terminal = 1; 
-
-  FM_Reader reader(fn.c_str());
+  _reader = new FM_Reader((char*)fn);
+}
 
-  for (int i=0;i<reader.GetNumFaces();i++) {
-    add(new FFace(this, reader.GetFace(i), i));
+void F_Internals::buildGModel(GModel *model)
+{
+  // building geom vertices
+  int nVertices = _reader->GetNumVertices();
+  for (int i=0;i<nVertices;i++) {
+    FVertex* v = new FVertex(model,i,_reader->GetVertex(i));
+    model->add(v);
+  }
+  // building geom edges
+  int nEdges = _reader->GetNumEdges();
+  for (int i=0;i<nEdges;i++) {
+    FM_Edge* edge = _reader->GetEdge(i);
+    int i1 = edge->GetStartPoint()->GetTag();
+    int i2 = edge->GetEndPoint()->GetTag();
+    GVertex *v1 = model->vertexByTag(i1);
+    GVertex *v2 = model->vertexByTag(i2);
+    FEdge *e = new FEdge(model, edge, i, v1, v2);
+    model->add(e);
   }
-  Msg(INFO, "Fourier model created: %d patches", reader.GetNumFaces());
+  // building geom faces
+  int nFaces = _reader->GetNumFaces();
+  for(int i=0;i<nFaces;i++){
+    FM_Face* face = _reader->GetFace(i);
+    std::list<GEdge*> l_edges;
+    for (int j=0;j<face->GetNumEdges();j++) {
+      int tag = face->GetEdge(j)->GetTag(); 
+     l_edges.push_back(model->edgeByTag(tag));
+    }
+    FFace *f = new FFace(model, face, i, l_edges);
+    model->add(f);
+  }
+}
+
+int GModel::readF(const std::string &fn)
+{
+  f_internals = new F_Internals;
+  f_internals->loadF(fn.c_str());
+  f_internals->buildGModel(this);
 
   return 1;
 }
diff --git a/Geo/GModelIO_F.h b/Geo/GModelIO_F.h
new file mode 100644
index 0000000000000000000000000000000000000000..fadcadd75fea9ecdb2e747bdc2f6616149f2fc63
--- /dev/null
+++ b/Geo/GModelIO_F.h
@@ -0,0 +1,19 @@
+#ifndef _GMODELIO_F_H_
+#define _GMODELIO_F_H_
+
+#include "GModel.h"
+#include "FM_Reader.h"
+
+#if defined(HAVE_FOURIER_MODEL)
+
+class F_Internals {
+ protected:
+  FM_Reader* _reader;
+ public:
+  F_Internals() : _reader(0) {}
+  void loadF(const char *);
+  void buildGModel(GModel *gm);
+};
+
+#endif
+#endif
diff --git a/contrib/FourierModel/FM_Edge.h b/contrib/FourierModel/FM_Edge.h
index c80c7b872ac697b9f8d4442e2acdd6dfb3f599ef..203756644da322a357550f44812bbb41f8c56b39 100644
--- a/contrib/FourierModel/FM_Edge.h
+++ b/contrib/FourierModel/FM_Edge.h
@@ -6,19 +6,22 @@
 
 class FM_Edge {
  private:
+  int _tag;
   Curve* _curve;
   FM_Vertex* _SP;
   FM_Vertex* _EP;
  public:
-  FM_Edge() : _curve(0), _SP(0), _EP(0) {}
-  FM_Edge(Curve* curve) : _curve(curve), _SP(0), _EP(0) {}
-  FM_Edge(Curve* curve, FM_Vertex* SP, FM_Vertex* EP) : 
-    _curve(curve), _SP(SP), _EP(EP) {}
+  FM_Edge() : _tag(-1), _curve(0), _SP(0), _EP(0) {}
+  FM_Edge(Curve* curve) : _tag(-1), _curve(curve), _SP(0), _EP(0) {}
+  FM_Edge(int tag, Curve* curve, FM_Vertex* SP, FM_Vertex* EP) : 
+    _tag(tag), _curve(curve), _SP(SP), _EP(EP) {}
   virtual ~FM_Edge() {}
 
+  inline int GetTag() { return _tag; }
   inline FM_Vertex* GetStartPoint() { return _SP; }
   inline FM_Vertex* GetEndPoint() { return _EP; }
 
+  inline void SetTag(int tag) { _tag = tag; }
   inline void SetStartPoint(FM_Vertex* SP) { _SP = SP; }
   inline void SetStartPoint(double x, double y, double z) { 
     _SP = new FM_Vertex(x,y,z); 
diff --git a/contrib/FourierModel/FM_Face.h b/contrib/FourierModel/FM_Face.h
index f8f7a6e0c17a2cfcb46fbed12bcc84787e58a435..7a5dc5b195d4d852692b34001939b9c3edf9fa9b 100644
--- a/contrib/FourierModel/FM_Face.h
+++ b/contrib/FourierModel/FM_Face.h
@@ -6,15 +6,21 @@
 
 class FM_Face {
  private:
+  int _tag;
   Patch* _patch;
   std::vector<FM_Edge*> _edge;
  public:
-  FM_Face() : _patch(0) {}
-  FM_Face(Patch* patch) : _patch(patch) {}
+  FM_Face() : _tag(-1), _patch(0) {}
+  FM_Face(Patch* patch) : _tag(-1), _patch(patch) {}
+  FM_Face(int tag, Patch* patch) : _tag(tag), _patch(patch) {}
   FM_Face(Patch* patch, std::vector<FM_Edge*> edge) :
-    _patch(patch), _edge(edge) {}
+    _tag(-1), _patch(patch), _edge(edge) {}
+  FM_Face(int tag, Patch* patch, std::vector<FM_Edge*> edge) :
+    _tag(tag), _patch(patch), _edge(edge) {}
   virtual ~FM_Face() {}
 
+  inline void SetTag(int tag) { _tag = tag; }
+  inline int GetTag() { return _tag; }
   inline void AddEdge(FM_Edge* edge) { _edge.push_back(edge); }
   inline int GetNumEdges() { return _edge.size(); }
   inline FM_Edge* GetEdge(int i) { return _edge[i]; }
diff --git a/contrib/FourierModel/FM_Reader.cpp b/contrib/FourierModel/FM_Reader.cpp
index 37cfa6c072cb362f1f01ea76bbd50406adb393c1..7f5398857df0ef27eb09f243e80d7a9ba5e15dff 100644
--- a/contrib/FourierModel/FM_Reader.cpp
+++ b/contrib/FourierModel/FM_Reader.cpp
@@ -68,27 +68,34 @@ FM_Reader::FM_Reader(const char* fn)
     _intersection[II->tag] = new Curve(II,_patch);
   }
 
+  InputFile >> _nVertices;
+  for (int i=0;i<_nVertices;i++) {
+    double x,y,z;
+    InputFile >> x >> y >> z;
+    _vertex.push_back(new FM_Vertex(i,x,y,z));
+  }
+
+  InputFile >> _nEdges;
+  for (int i=0;i<_nEdges;i++) {
+    int edgeTag, svTag, evTag;
+    InputFile >> edgeTag >> svTag >> evTag;
+    if (edgeTag < 0)
+      _edge.push_back(new FM_Edge(i,0,_vertex[svTag],_vertex[evTag]));
+    else
+      _edge.push_back(new FM_Edge(i,GetIntersection(edgeTag),
+				  _vertex[svTag],_vertex[evTag]));
+  }
+
   InputFile >> _nFaces;
   for (int i=0;i<_nFaces;i++) {
     int faceTag, nEdges;
     InputFile >> faceTag;
-    _face.push_back(new FM_Face(GetPatch(faceTag)));
+    _face.push_back(new FM_Face(i,GetPatch(faceTag)));
     InputFile >> nEdges;
     for (int j=0;j<nEdges;j++) {
       int edgeTag;
-      double SPx,SPy,SPz;
-      double EPx,EPy,EPz;
       InputFile >> edgeTag;
-      InputFile >> SPx >> SPy >> SPz;
-      InputFile >> EPx >> EPy >> EPz;
-      if (edgeTag < 0)
-	_face[i]->AddEdge(new FM_Edge(0,
-				      new FM_Vertex(SPx,SPy,SPz),
-				      new FM_Vertex(EPx,EPy,EPz)));
-      else
-	_face[i]->AddEdge(new FM_Edge(GetIntersection(edgeTag),
-				      new FM_Vertex(SPx,SPy,SPz),
-				      new FM_Vertex(EPx,EPy,EPz)));
+      _face[i]->AddEdge(_edge[edgeTag]);
     }
   }
 }
diff --git a/contrib/FourierModel/FM_Reader.h b/contrib/FourierModel/FM_Reader.h
index 98940271bfb60d133a035d59eac9b48829eec5cb..c7ddcf5da5c79fb3bb24a43b115a39578386db98 100644
--- a/contrib/FourierModel/FM_Reader.h
+++ b/contrib/FourierModel/FM_Reader.h
@@ -11,11 +11,15 @@
 
 class FM_Reader {
  private:
+  int _nVertices;
+  int _nEdges;
   int _nFaces;
   int _nPatches;
   int _nIntersections;
   std::vector<PatchInfo*> _patchList;
   std::vector<IntersectionInfo*> _intersectionList;
+  std::vector<FM_Vertex*> _vertex;
+  std::vector<FM_Edge*> _edge;
   std::vector<FM_Face*> _face;
   std::vector<Patch*> _patch;
   std::vector<Curve*> _intersection;
@@ -23,12 +27,16 @@ class FM_Reader {
   FM_Reader(const char* fn);
   virtual ~FM_Reader() {}
 
+  inline int GetNumVertices() { return _nVertices; }
+  inline int GetNumEdges() { return _nEdges; }
   inline int GetNumFaces() { return _nFaces; }
   inline int GetNumPatches() { return _nPatches; }
   inline int GetNumIntersections() { return _nIntersections; }
   inline std::vector<PatchInfo*> GetPatchList() { return _patchList; }
   inline std::vector<IntersectionInfo*> GetIntersectionList()
     { return _intersectionList; }
+  inline FM_Vertex* GetVertex(int i) { return _vertex[i]; }
+  inline FM_Edge* GetEdge(int i) { return _edge[i]; }
   inline FM_Face* GetFace(int i) { return _face[i]; }
 
   Patch* GetPatch(int tag);
diff --git a/contrib/FourierModel/FM_Vertex.h b/contrib/FourierModel/FM_Vertex.h
index 2bc0fe0caef36b80630571b99d16f6afea6ec573..b166b7f4fa76aa90fbd13e4e3ed57ad1661e7f38 100644
--- a/contrib/FourierModel/FM_Vertex.h
+++ b/contrib/FourierModel/FM_Vertex.h
@@ -3,16 +3,21 @@
 
 class FM_Vertex {
  private:
+  int _tag;
   double _x,_y,_z;
  public:
-  FM_Vertex() : _x(0), _y(0), _z(0) {}
-  FM_Vertex(double x, double y, double z) : _x(x), _y(y), _z(z) {}
+  FM_Vertex() : _tag(-1), _x(0), _y(0), _z(0) {}
+  FM_Vertex(double x, double y, double z) : _tag(-1), _x(x), _y(y), _z(z) {}
+  FM_Vertex(int tag, double x, double y, double z) : _tag(tag), 
+    _x(x), _y(y), _z(z) {}
   virtual ~FM_Vertex() {}
 
+  inline int GetTag() { return _tag; }
   inline double GetX() { return _x; }
   inline double GetY() { return _y; }
   inline double GetZ() { return _z; }
 
+  inline void SetTag(int tag) { _tag = tag; }
   inline void SetX(double x) { _x = x; }
   inline void SetY(double y) { _y = y; }
   inline void SetZ(double z) { _z = z; }