From af2a4e84bde774bebdcd9eb9578928828888fbda Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Thu, 3 May 2007 08:50:02 +0000 Subject: [PATCH] add test version of fourier model --- Geo/FEdge.cpp | 25 + Geo/FEdge.h | 41 + Geo/FFace.cpp | 74 ++ Geo/FFace.h | 49 ++ Geo/FVertex.h | 43 + Geo/GModel.h | 2 +- Geo/GModelIO_F.cpp | 52 ++ Geo/Makefile | 36 +- Parser/OpenFile.cpp | 904 +++++++++++---------- configure | 45 +- configure.in | 30 +- contrib/FourierModel/ContinuationPatch.cpp | 500 ++++++++++++ contrib/FourierModel/ContinuationPatch.h | 63 ++ contrib/FourierModel/Curve.cpp | 242 ++++++ contrib/FourierModel/Curve.h | 37 + contrib/FourierModel/ExactPatch.cpp | 192 +++++ contrib/FourierModel/ExactPatch.h | 30 + contrib/FourierModel/FM_Edge.cpp | 123 +++ contrib/FourierModel/FM_Edge.h | 37 + contrib/FourierModel/FM_Face.cpp | 147 ++++ contrib/FourierModel/FM_Face.h | 33 + contrib/FourierModel/FM_Info.cpp | 1 + contrib/FourierModel/FM_Info.h | 37 + contrib/FourierModel/FM_Reader.cpp | 108 +++ contrib/FourierModel/FM_Reader.h | 38 + contrib/FourierModel/FM_Vertex.cpp | 2 + contrib/FourierModel/FM_Vertex.h | 21 + contrib/FourierModel/Main.cpp | 117 +++ contrib/FourierModel/Makefile | 55 ++ contrib/FourierModel/Message.cpp | 156 ++++ contrib/FourierModel/Message.h | 36 + contrib/FourierModel/Patch.cpp | 84 ++ contrib/FourierModel/Patch.h | 40 + 33 files changed, 2905 insertions(+), 495 deletions(-) create mode 100644 Geo/FEdge.cpp create mode 100644 Geo/FEdge.h create mode 100644 Geo/FFace.cpp create mode 100644 Geo/FFace.h create mode 100644 Geo/FVertex.h create mode 100644 Geo/GModelIO_F.cpp create mode 100644 contrib/FourierModel/ContinuationPatch.cpp create mode 100644 contrib/FourierModel/ContinuationPatch.h create mode 100644 contrib/FourierModel/Curve.cpp create mode 100644 contrib/FourierModel/Curve.h create mode 100644 contrib/FourierModel/ExactPatch.cpp create mode 100644 contrib/FourierModel/ExactPatch.h create mode 100644 contrib/FourierModel/FM_Edge.cpp create mode 100644 contrib/FourierModel/FM_Edge.h create mode 100644 contrib/FourierModel/FM_Face.cpp create mode 100644 contrib/FourierModel/FM_Face.h create mode 100644 contrib/FourierModel/FM_Info.cpp create mode 100644 contrib/FourierModel/FM_Info.h create mode 100644 contrib/FourierModel/FM_Reader.cpp create mode 100644 contrib/FourierModel/FM_Reader.h create mode 100644 contrib/FourierModel/FM_Vertex.cpp create mode 100644 contrib/FourierModel/FM_Vertex.h create mode 100644 contrib/FourierModel/Main.cpp create mode 100644 contrib/FourierModel/Makefile create mode 100644 contrib/FourierModel/Message.cpp create mode 100644 contrib/FourierModel/Message.h create mode 100644 contrib/FourierModel/Patch.cpp create mode 100644 contrib/FourierModel/Patch.h diff --git a/Geo/FEdge.cpp b/Geo/FEdge.cpp new file mode 100644 index 0000000000..545c57024d --- /dev/null +++ b/Geo/FEdge.cpp @@ -0,0 +1,25 @@ +#include "FEdge.h" + +#if defined(HAVE_FOURIER_MODEL) + +Range<double> FEdge::parBounds(int i) const +{ + return(Range<double>(0.,1.)); +} + +GPoint FEdge::point(double p) const +{ + double x, y, z; + + edge->F(p,x,y,z); + return GPoint(x,y,z); +} + +double FEdge::parFromPoint(const SPoint3 &pt) const +{ + double t; + edge->Inverse(pt.x(),pt.y(),pt.z(),t); + return t; +} + +#endif diff --git a/Geo/FEdge.h b/Geo/FEdge.h new file mode 100644 index 0000000000..ba59a9378c --- /dev/null +++ b/Geo/FEdge.h @@ -0,0 +1,41 @@ +#ifndef _F_EDGE_H_ +#define _F_EDGE_H_ + +#include "GEdge.h" +#include "GModel.h" +#include "FVertex.h" +#include "Range.h" + +#if defined(HAVE_FOURIER_MODEL) + +#include "FM_Edge.h" + +class FEdge : public GEdge { + protected: + FM_Edge* edge; + public: + FEdge(GModel *model, FM_Edge* edge_, int tag, GVertex *v1, GVertex *v2) : + GEdge(model, tag, v1, v2), edge(edge_) {} + virtual ~FEdge() {} + 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 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 double parFromPoint(const SPoint3 &pt) const; + virtual int minimumMeshSegments () const { throw; } + virtual int minimumDrawSegments () const { throw; } + ModelType getNativeType() const { return FourierModel; } +}; + +#endif + +#endif diff --git a/Geo/FFace.cpp b/Geo/FFace.cpp new file mode 100644 index 0000000000..6640975444 --- /dev/null +++ b/Geo/FFace.cpp @@ -0,0 +1,74 @@ +#include "FVertex.h" +#include "FFace.h" + +#if defined(HAVE_FOURIER_MODEL) + +FFace::FFace(GModel *m, FM_Face *face_, int tag) : GFace(m,tag), face(face_) +{ + int curCorner = 0; + for (int i=0;i<face->GetNumEdges();i++) { + GVertex* p0 = new FVertex(m,curCorner,face->GetEdge(i)->GetStartPoint()); + curCorner = (curCorner + 1) % face->GetNumEdges(); + GVertex* p1 = new FVertex(m,curCorner,face->GetEdge(i)->GetEndPoint()); + l_edges.push_back(new FEdge(m,face->GetEdge(i),i,p0,p1)); + l_dirs.push_back(1); + } +} + +Range<double> FFace::parBounds(int i) const +{ + return Range<double>(0.,1.); +} + +GPoint FFace::point(double par1, double par2) const +{ + double pp[2] = {par1,par2}; + double x,y,z; + face->F(par1,par2,x,y,z); + return GPoint(x, y, z, this, pp); +} + +GPoint FFace::point(const SPoint2 &pt) const +{ + return point(pt[0], pt[1]); +} + +SPoint2 FFace::parFromPoint(const SPoint3 &p) const +{ + double u, v, x, y, z; + x = p.x(); y = p.y(); z = p.z(); + face->Inverse(x,y,z,u,v); + return SPoint2(u, v); +} + +GPoint FFace::closestPoint(const SPoint3 & queryPoint) const +{ + throw; +} + +int FFace::containsPoint(const SPoint3 &pt) const +{ + throw; +} + +int FFace::containsParam(const SPoint2 &pt) const +{ + const double tol = 1.e-6; + if(pt[0] < 0. - tol || pt[0] > 1. + tol) return 0; + if(pt[1] < 0. - tol || pt[1] > 1. + tol) return 0; + return 1; +} + +SVector3 FFace::normal(const SPoint2 ¶m) const +{ + double x,y,z; + face->GetUnitNormal(param[0],param[1],x,y,z); + return SVector3(x, y, z); +} + +GEntity::GeomType FFace::geomType() const +{ + return GEntity::ParametricSurface; +} + +#endif diff --git a/Geo/FFace.h b/Geo/FFace.h new file mode 100644 index 0000000000..5c6bb11b8f --- /dev/null +++ b/Geo/FFace.h @@ -0,0 +1,49 @@ +#ifndef _F_FACE_H_ +#define _F_FACE_H_ + +#include "GFace.h" +#include "GModel.h" +#include "Range.h" +#include "FEdge.h" + +#if defined(HAVE_FOURIER_MODEL) + +#include "FM_Face.h" + +class FFace : public GFace { + protected: + FM_Face *face; + bool _periodic[2]; + public: + FFace(GModel *m, FM_Face *face_, int tag); + + virtual ~FFace() {} + + Range<double> parBounds(int i) const; + virtual int paramDegeneracies(int dir, double *par) { return 0; } + virtual GPoint point(double par1, double par2) const; + virtual GPoint point(const SPoint2 &pt) const; + virtual SPoint2 parFromPoint(const SPoint3 &p) const; + virtual GPoint closestPoint(const SPoint3 & queryPoint) const; + virtual int containsPoint(const SPoint3 &pt) const; + virtual int containsParam(const SPoint2 &pt) const; + virtual SVector3 normal(const SPoint2 ¶m) const; + virtual GEntity::GeomType geomType() const; + virtual Pair<SVector3,SVector3> + firstDer(const SPoint2 ¶m) const {throw;} + virtual double * nthDerivative + (const SPoint2 ¶m, int n, double *array) const {throw;} + virtual int geomDirection() const { return 1; } + virtual bool continuous(int dim) const { return true; } + virtual bool periodic(int dim) const { return false; } + virtual bool degenerate(int dim) const { return false; } + virtual double period(int dir) const {throw;} + ModelType getNativeType() const { return FourierModel; } + void * getNativePtr() const {throw;} + virtual bool surfPeriodic(int dim) const {throw;} +}; + +#endif + +#endif + diff --git a/Geo/FVertex.h b/Geo/FVertex.h new file mode 100644 index 0000000000..481e16fe03 --- /dev/null +++ b/Geo/FVertex.h @@ -0,0 +1,43 @@ +#ifndef _F_VERTEX_H_ +#define _F_VERTEX_H_ + +#include "GModel.h" +#include "GVertex.h" + +#if defined(HAVE_FOURIER_MODEL) + +#include "FM_Vertex.h" + +class FVertex : public GVertex { + protected: + FM_Vertex* v; + + public: + FVertex(GModel *m, int num, FM_Vertex* _v) : GVertex(m, num), v(_v) + { + mesh_vertices.push_back(new MVertex(x(), y(), z(), this)); + } + virtual ~FVertex() {} + virtual GPoint point() const + { + return GPoint(x(),y(),z()); + } + virtual double x() const + { + return v->GetX(); + } + virtual double y() const + { + return v->GetY(); + } + virtual double z() const + { + return v->GetZ(); + } + ModelType getNativeType() const { return FourierModel; } + virtual SPoint2 reparamOnFace ( GFace *gf , int) const { throw; } +}; + +#endif + +#endif diff --git a/Geo/GModel.h b/Geo/GModel.h index e03636bb6d..20487dd475 100644 --- a/Geo/GModel.h +++ b/Geo/GModel.h @@ -167,7 +167,7 @@ class GModel int writeGEO(const std::string &name, bool printLabels=true); // Fourier model - int readFourier(const std::string &name); + int readF(const std::string &name); // OCC model int readOCCBREP(const std::string &name); diff --git a/Geo/GModelIO_F.cpp b/Geo/GModelIO_F.cpp new file mode 100644 index 0000000000..c096b4a63f --- /dev/null +++ b/Geo/GModelIO_F.cpp @@ -0,0 +1,52 @@ +#include <string> +#include "GModel.h" +#include "Message.h" +#include "Context.h" +#include "Views.h" +#include "FFace.h" +#include "meshGFace.h" + +#if defined(HAVE_FOURIER_MODEL) + +#include "FM_Reader.h" + +extern Context_T CTX; + +class meshGmsh{ +public: + void operator() (GFace *gf) + { + FFace *ff = dynamic_cast<FFace*>(gf); + if(!ff) { + Msg(GERROR, "face %d is not Fourier", gf->tag()); + return; + } + meshGFace mesh; + mesh(ff); + } +}; + +int GModel::readF(const std::string &fn) +{ + CTX.terminal = 1; + + FM_Reader reader(fn.c_str()); + + for (int i=0;i<reader.GetNumFaces();i++) { + add(new FFace(this, reader.GetFace(i), i)); + } + Msg(INFO, "Fourier model created: %d patches", reader.GetNumFaces()); + + return 1; +} + +#else + +int GModel::readF(const std::string &fn) +{ + Msg(GERROR,"Gmsh has to be compiled with Fourier Model support to load %s", + fn.c_str()); + return 0; +} + +#endif diff --git a/Geo/Makefile b/Geo/Makefile index a4ea4b0aac..d818f5efe8 100644 --- a/Geo/Makefile +++ b/Geo/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.143 2007-04-23 08:04:16 geuzaine Exp $ +# $Id: Makefile,v 1.144 2007-05-03 08:50:01 geuzaine Exp $ # # Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle # @@ -30,12 +30,13 @@ SRC = GEntity.cpp\ GVertex.cpp GEdge.cpp GEdgeLoop.cpp GFace.cpp GRegion.cpp\ gmshVertex.cpp gmshEdge.cpp gmshFace.cpp gmshRegion.cpp gmshSurface.cpp\ OCCVertex.cpp OCCEdge.cpp OCCFace.cpp OCCRegion.cpp\ + FEdge.cpp FFace.cpp\ projectionFace.cpp\ GModel.cpp\ GModelIO_Geo.cpp\ GModelIO_Mesh.cpp\ - GModelIO_Fourier.cpp\ GModelIO_OCC.cpp\ + GModelIO_F.cpp\ GModelIO_CGNS.cpp\ GModelIO_MED.cpp\ ExtrudeParams.cpp \ @@ -160,6 +161,18 @@ OCCRegion.o: OCCRegion.cpp GModel.h GVertex.h GEntity.h Range.h SPoint3.h \ ExtrudeParams.h ../Common/SmoothData.h GFace.h GEdgeLoop.h Pair.h \ GRegion.h OCCVertex.h OCCIncludes.h OCCEdge.h OCCFace.h OCCRegion.h \ ../Common/Message.h +FEdge.o: FEdge.cpp FEdge.h GEdge.h GEntity.h Range.h SPoint3.h \ + SBoundingBox3d.h ../Common/GmshDefines.h GVertex.h MVertex.h GPoint.h \ + SPoint2.h SVector3.h MElement.h MEdge.h ../Common/Hash.h MFace.h \ + ../Numeric/Numeric.h ../Common/Context.h ../DataStr/List.h \ + ExtrudeParams.h ../Common/SmoothData.h GModel.h GFace.h GEdgeLoop.h \ + Pair.h GRegion.h FVertex.h +FFace.o: FFace.cpp FVertex.h GModel.h GVertex.h GEntity.h Range.h \ + SPoint3.h SBoundingBox3d.h ../Common/GmshDefines.h MVertex.h GPoint.h \ + SPoint2.h GEdge.h SVector3.h MElement.h MEdge.h ../Common/Hash.h \ + MFace.h ../Numeric/Numeric.h ../Common/Context.h ../DataStr/List.h \ + ExtrudeParams.h ../Common/SmoothData.h GFace.h GEdgeLoop.h Pair.h \ + GRegion.h FFace.h FEdge.h projectionFace.o: projectionFace.cpp projectionFace.h GFace.h GPoint.h \ GEntity.h Range.h SPoint3.h SBoundingBox3d.h ../Common/GmshDefines.h \ GEdgeLoop.h GEdge.h GVertex.h MVertex.h SPoint2.h SVector3.h MElement.h \ @@ -195,16 +208,6 @@ GModelIO_Mesh.o: GModelIO_Mesh.cpp ../Common/Message.h \ ../Common/SmoothData.h GFace.h GEdgeLoop.h Pair.h GRegion.h \ gmshRegion.h Geo.h gmshSurface.h ../DataStr/Tree.h ../DataStr/avl.h \ gmshFace.h gmshVertex.h gmshEdge.h -GModelIO_Fourier.o: GModelIO_Fourier.cpp GModel.h GVertex.h GEntity.h \ - Range.h SPoint3.h SBoundingBox3d.h ../Common/GmshDefines.h MVertex.h \ - GPoint.h SPoint2.h GEdge.h SVector3.h MElement.h MEdge.h \ - ../Common/Hash.h MFace.h ../Numeric/Numeric.h ../Common/Context.h \ - ../DataStr/List.h ExtrudeParams.h ../Common/SmoothData.h GFace.h \ - GEdgeLoop.h Pair.h GRegion.h fourierFace.h gmshFace.h Geo.h \ - gmshSurface.h ../DataStr/Tree.h ../DataStr/avl.h gmshVertex.h \ - ../Common/Message.h ../Common/Views.h ../Common/ColorTable.h \ - ../Common/VertexArray.h ../Common/SmoothData.h \ - ../Common/AdaptiveViews.h ../Common/GmshMatrix.h GModelIO_OCC.o: GModelIO_OCC.cpp GModelIO_OCC.h GModel.h GVertex.h \ GEntity.h Range.h SPoint3.h SBoundingBox3d.h ../Common/GmshDefines.h \ MVertex.h GPoint.h SPoint2.h GEdge.h SVector3.h MElement.h MEdge.h \ @@ -212,6 +215,15 @@ GModelIO_OCC.o: GModelIO_OCC.cpp GModelIO_OCC.h GModel.h GVertex.h \ ../DataStr/List.h ExtrudeParams.h ../Common/SmoothData.h GFace.h \ GEdgeLoop.h Pair.h GRegion.h OCCIncludes.h ../Common/Message.h \ OCCVertex.h OCCEdge.h OCCFace.h OCCRegion.h +GModelIO_F.o: GModelIO_F.cpp GModel.h GVertex.h GEntity.h Range.h \ + SPoint3.h SBoundingBox3d.h ../Common/GmshDefines.h MVertex.h GPoint.h \ + SPoint2.h GEdge.h SVector3.h MElement.h MEdge.h ../Common/Hash.h \ + MFace.h ../Numeric/Numeric.h ../Common/Context.h ../DataStr/List.h \ + ExtrudeParams.h ../Common/SmoothData.h GFace.h GEdgeLoop.h Pair.h \ + GRegion.h ../Common/Message.h ../Common/Views.h ../Common/ColorTable.h \ + ../Common/VertexArray.h ../Common/SmoothData.h \ + ../Common/AdaptiveViews.h ../Common/GmshMatrix.h FFace.h FEdge.h \ + FVertex.h ../Mesh/meshGFace.h GModelIO_CGNS.o: GModelIO_CGNS.cpp GModel.h GVertex.h GEntity.h Range.h \ SPoint3.h SBoundingBox3d.h ../Common/GmshDefines.h MVertex.h GPoint.h \ SPoint2.h GEdge.h SVector3.h MElement.h MEdge.h ../Common/Hash.h \ diff --git a/Parser/OpenFile.cpp b/Parser/OpenFile.cpp index 7474acff9d..0024d2836b 100644 --- a/Parser/OpenFile.cpp +++ b/Parser/OpenFile.cpp @@ -1,450 +1,454 @@ -// $Id: OpenFile.cpp,v 1.145 2007-03-16 10:03:40 remacle Exp $ -// -// Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program 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 General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -// USA. -// -// Please report all bugs and problems to <gmsh@geuz.org>. - -#if defined(__CYGWIN__) -#include <sys/cygwin.h> -#endif - -#include "Gmsh.h" -#include "Geo.h" -#include "GModel.h" -#include "Numeric.h" -#include "Context.h" -#include "Parser.h" -#include "OpenFile.h" -#include "CommandLine.h" -#include "Views.h" -#include "ReadImg.h" -#include "OS.h" -#include "HighOrder.h" - -#if defined(HAVE_FLTK) -#include "GmshUI.h" -#include "Draw.h" -#include "SelectBuffer.h" -#include "GUI.h" -extern GUI *WID; -void UpdateViewsInGUI(); -#endif - -extern Mesh *THEM; -extern GModel *GMODEL; -extern Context_T CTX; - -void FixRelativePath(char *in, char *out){ - if(in[0] == '/' || in[0] == '\\' || (strlen(in)>2 && in[1] == ':')){ - // do nothing: 'in' is an absolute path - strcpy(out, in); - } - else{ - // append 'in' to the path of the parent file - strcpy(out, yyname); - int i = strlen(out)-1 ; - while(i >= 0 && yyname[i] != '/' && yyname[i] != '\\') i-- ; - out[i+1] = '\0'; - strcat(out, in); - } -} - -void FixWindowsPath(char *in, char *out){ -#if defined(__CYGWIN__) - cygwin_conv_to_win32_path(in, out); -#else - strcpy(out, in); -#endif -} - -void SplitFileName(char *name, char *base, char *ext) -{ - strcpy(base, name); - strcpy(ext, ""); - for(int i = strlen(name)-1; i >= 0; i--){ - if(name[i] == '.'){ - strcpy(ext, &name[i]); - base[i] = '\0'; - break; - } - } -} - -static void FinishUpBoundingBox() -{ - double range[3]; - - for(int i = 0; i < 3; i++){ - CTX.cg[i] = 0.5 * (CTX.min[i] + CTX.max[i]); - range[i] = CTX.max[i] - CTX.min[i]; - } - - if(range[0] == 0. && range[1] == 0. && range[2] == 0.) { - CTX.min[0] -= 1.; CTX.min[1] -= 1.; - CTX.max[0] += 1.; CTX.max[1] += 1.; - CTX.lc = 1.; - } - else if(range[0] == 0. && range[1] == 0.) { - CTX.lc = range[2]; - CTX.min[0] -= CTX.lc; CTX.min[1] -= CTX.lc; - CTX.max[0] += CTX.lc; CTX.max[1] += CTX.lc; - } - else if(range[0] == 0. && range[2] == 0.) { - CTX.lc = range[1]; - CTX.min[0] -= CTX.lc; CTX.max[0] += CTX.lc; - } - else if(range[1] == 0. && range[2] == 0.) { - CTX.lc = range[0]; - CTX.min[1] -= CTX.lc; CTX.max[1] += CTX.lc; - } - else if(range[0] == 0.) { - CTX.lc = sqrt(DSQR(range[1]) + DSQR(range[2])); - CTX.min[0] -= CTX.lc; CTX.max[0] += CTX.lc; - } - else if(range[1] == 0.) { - CTX.lc = sqrt(DSQR(range[0]) + DSQR(range[2])); - CTX.min[1] -= CTX.lc; CTX.max[1] += CTX.lc; - } - else if(range[2] == 0.) { - CTX.lc = sqrt(DSQR(range[0]) + DSQR(range[1])); - } - else { - CTX.lc = sqrt(DSQR(range[0]) + DSQR(range[1]) + DSQR(range[2])); - } -} - -void SetBoundingBox(double xmin, double xmax, - double ymin, double ymax, - double zmin, double zmax) -{ - CTX.min[0] = xmin; CTX.max[0] = xmax; - CTX.min[1] = ymin; CTX.max[1] = ymax; - CTX.min[2] = zmin; CTX.max[2] = zmax; - FinishUpBoundingBox(); -} - -void SetBoundingBox(void) -{ - if(CTX.forced_bbox) return; - - SBoundingBox3d bb; - - bb = GMODEL->bounds(); - - if(bb.empty() && List_Nbr(CTX.post.list)) { - for(int i = 0; i < List_Nbr(CTX.post.list); i++){ - Post_View *v = *(Post_View **)List_Pointer(CTX.post.list, i); - if(fabs(v->BBox[0]) != VAL_INF && - fabs(v->BBox[2]) != VAL_INF && - fabs(v->BBox[4]) != VAL_INF) - bb += SPoint3(v->BBox[0], v->BBox[2], v->BBox[4]); - if(fabs(v->BBox[1]) != VAL_INF && - fabs(v->BBox[3]) != VAL_INF && - fabs(v->BBox[5]) != VAL_INF) - bb += SPoint3(v->BBox[1], v->BBox[3], v->BBox[5]); - } - } - - if(bb.empty()){ - bb += SPoint3(-1., -1., -1.); - bb += SPoint3(1., 1., 1.); - } - - CTX.min[0] = bb.min().x(); CTX.max[0] = bb.max().x(); - CTX.min[1] = bb.min().y(); CTX.max[1] = bb.max().y(); - CTX.min[2] = bb.min().z(); CTX.max[2] = bb.max().z(); - FinishUpBoundingBox(); -} - -// FIXME: this is necessary for now to have an approximate CTX.lc -// *while* parsing input files (it's important since some of the -// geometrical operations use a tolerance that depends on -// CTX.lc). This will be removed once the new database is filled -// directly during the parsing step -static SBoundingBox3d temp_bb; - -void ResetTemporaryBoundingBox() -{ - temp_bb.reset(); -} - -void AddToTemporaryBoundingBox(double x, double y, double z) -{ - temp_bb += SPoint3(x, y, z); - CTX.min[0] = temp_bb.min().x(); CTX.max[0] = temp_bb.max().x(); - CTX.min[1] = temp_bb.min().y(); CTX.max[1] = temp_bb.max().y(); - CTX.min[2] = temp_bb.min().z(); CTX.max[2] = temp_bb.max().z(); - FinishUpBoundingBox(); -} - -int ParseFile(char *f, int close, int warn_if_missing) -{ - char yyname_old[256], tmp[256]; - FILE *yyin_old, *fp; - int yylineno_old, yyerrorstate_old, numviews_old; - - // add 'b' for pure Windows programs: opening in text mode messes up - // fsetpos/fgetpos (used e.g. for user-defined functions) - if(!(fp = fopen(f, "rb"))){ - if(warn_if_missing) Msg(WARNING, "Unable to open file '%s'", f); - return 0; - } - - strncpy(yyname_old, yyname, 255); - yyin_old = yyin; - yyerrorstate_old = yyerrorstate; - yylineno_old = yylineno; - numviews_old = List_Nbr(CTX.post.list); - - strncpy(yyname, f, 255); - yyin = fp; - yyerrorstate = 0; - yylineno = 1; - - fpos_t position; - fgetpos(yyin, &position); - fgets(tmp, sizeof(tmp), yyin); - fsetpos(yyin, &position); - - while(!feof(yyin)){ - yyparse(); - if(yyerrorstate > 20){ - Msg(GERROR, "Too many errors: aborting..."); - force_yyflush(); - break; - } - } - - if(close) - fclose(yyin); - - strncpy(yyname, yyname_old, 255); - yyin = yyin_old; - yyerrorstate = yyerrorstate_old; - yylineno = yylineno_old; - - if(List_Nbr(CTX.post.list) != numviews_old){ -#if defined(HAVE_FLTK) - UpdateViewsInGUI(); -#endif - } - - return 1; -} - -void ParseString(char *str) -{ - if(!str) return; - FILE *fp; - if((fp = fopen(CTX.tmp_filename_fullpath, "w"))) { - fprintf(fp, str); - fprintf(fp, "\n"); - fclose(fp); - ParseFile(CTX.tmp_filename_fullpath, 1); - if(GMODEL) GMODEL->importTHEM(); - } -} - -void SetProjectName(char *name) -{ - char base[356], ext[256]; - SplitFileName(name, base, ext); - - strncpy(CTX.filename, name, 255); - strncpy(CTX.base_filename, base, 255); - -#if defined(HAVE_FLTK) - if(!CTX.batch) WID->set_title(CTX.filename); -#endif -} - -int MergeFile(char *name, int warn_if_missing) -{ -#if defined(HAVE_FOURIER_MODEL) - if(!strcmp(name, "falcon") || !strcmp(name, "ship")){ - GMODEL->readFourier(name); - SetBoundingBox(); - CTX.mesh.changed = ENT_ALL; - return 1; - } -#endif - - // added 'b' for pure Windows programs, since some of these files - // contain binary data - FILE *fp = fopen(name, "rb"); - if(!fp){ - if(warn_if_missing) Msg(WARNING, "Unable to open file '%s'", name); - return 0; - } - - char header[256]; - fgets(header, sizeof(header), fp); - fclose(fp); - - Msg(STATUS2, "Reading '%s'", name); - - char ext[256], base[256]; - SplitFileName(name, base, ext); - -#if defined(HAVE_FLTK) - if(!CTX.batch) { - if(!strcmp(ext, ".gz")) { - // the real solution would be to rewrite all our I/O functions in - // terms of gzFile, but until then, this is better than nothing - if(fl_choice("File '%s' is in gzip format.\n\nDo you want to uncompress it?", - "Cancel", "Uncompress", NULL, name)){ - char tmp[256]; - sprintf(tmp, "gunzip -c %s > %s", name, base); - SystemCall(tmp); - if(!strcmp(CTX.filename, name)) // this is the project file - SetProjectName(base); - return MergeFile(base); - } - } - } -#endif - - CTX.geom.draw = 0; // don't try to draw the model while reading - int status = 0; - if(!strcmp(ext, ".stl") || !strcmp(ext, ".STL")){ - status = GMODEL->readSTL(name, CTX.geom.tolerance); - } - else if(!strcmp(ext, ".brep") || !strcmp(ext, ".rle") || - !strcmp(ext, ".brp") || !strcmp(ext, ".BRP")){ - GMODEL->readOCCBREP(std::string(name)); - } - else if(!strcmp(ext, ".iges") || !strcmp(ext, ".IGES") || - !strcmp(ext, ".igs") || !strcmp(ext, ".IGS")){ - GMODEL->readOCCIGES(std::string(name)); - } - else if(!strcmp(ext, ".step") || !strcmp(ext, ".STEP") || - !strcmp(ext, ".stp") || !strcmp(ext, ".STP")){ - GMODEL->readOCCSTEP(std::string(name)); - } - else if(!strcmp(ext, ".unv") || !strcmp(ext, ".UNV")){ - status = GMODEL->readUNV(name); - } - else if(!strcmp(ext, ".wrl") || !strcmp(ext, ".WRL") || - !strcmp(ext, ".vrml") || !strcmp(ext, ".VRML") || - !strcmp(ext, ".iv") || !strcmp(ext, ".IV")){ - status = GMODEL->readVRML(name); - } - else if(!strcmp(ext, ".mesh") || !strcmp(ext, ".MESH")){ - status = GMODEL->readMESH(name); - } - else if(!strcmp(ext, ".bdf") || !strcmp(ext, ".BDF") || - !strcmp(ext, ".nas") || !strcmp(ext, ".NAS")){ - status = GMODEL->readBDF(name); - } - else if(!strcmp(ext, ".p3d") || !strcmp(ext, ".P3D")){ - status = GMODEL->readP3D(name); - } -#if defined(HAVE_FLTK) - else if(!strcmp(ext, ".pnm") || !strcmp(ext, ".PNM") || - !strcmp(ext, ".pbm") || !strcmp(ext, ".PBM") || - !strcmp(ext, ".pgm") || !strcmp(ext, ".PGM") || - !strcmp(ext, ".ppm") || !strcmp(ext, ".PPM")) { - status = read_pnm(name); - } - else if(!strcmp(ext, ".bmp") || !strcmp(ext, ".BMP")) { - status = read_bmp(name); - } -#if defined(HAVE_LIBJPEG) - else if(!strcmp(ext, ".jpg") || !strcmp(ext, ".JPG") || - !strcmp(ext, ".jpeg") || !strcmp(ext, ".JPEG")) { - status = read_jpeg(name); - } -#endif -#if defined(HAVE_LIBPNG) - else if(!strcmp(ext, ".png") || !strcmp(ext, ".PNG")) { - status = read_png(name); - } -#endif -#endif - else { - CTX.geom.draw = 1; - if(!strncmp(header, "$PTS", 4) || !strncmp(header, "$NO", 3) || - !strncmp(header, "$PARA", 5) || !strncmp(header, "$ELM", 4) || - !strncmp(header, "$MeshFormat", 11)) { - status = GMODEL->readMSH(name); - } - else if(!strncmp(header, "$PostFormat", 11) || - !strncmp(header, "$View", 5)) { - status = ReadView(name); - } - else { - status = GMODEL->readGEO(name); - } - } - - SetBoundingBox(); - - CTX.geom.draw = 1; - CTX.mesh.changed = ENT_ALL; - - checkHighOrderTriangles ( GMODEL ); - - Msg(STATUS2, "Read '%s'", name); - return status; -} - -void OpenProject(char *name) -{ - if(CTX.threads_lock) { - Msg(INFO, "I'm busy! Ask me that later..."); - return; - } - CTX.threads_lock = 1; - - GMODEL->destroy(); - THEM->destroy(); - - // Initialize pseudo random mesh generator to the same seed - srand(1); - - // temporary hack until we fill GMODEL on the fly during parsing - ResetTemporaryBoundingBox(); - - SetProjectName(name); - MergeFile(name); - - CTX.threads_lock = 0; - -#if defined(HAVE_FLTK) - if(!CTX.batch) WID->reset_visibility(); - ZeroHighlight(); -#endif -} - -void OpenProjectMacFinder(const char *filename) -{ - static int first = 1; - if(first || CTX.batch){ - // just copy the filename: it will be opened when the GUI is ready - // in main() - strncpy(CTX.filename, filename, 255); - first = 0; - } - else{ - OpenProject((char*)filename); -#if defined(HAVE_FLTK) - Draw(); -#endif - } -} - +// $Id: OpenFile.cpp,v 1.146 2007-05-03 08:50:02 geuzaine Exp $ +// +// Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to <gmsh@geuz.org>. + +#if defined(__CYGWIN__) +#include <sys/cygwin.h> +#endif + +#include "Gmsh.h" +#include "Geo.h" +#include "GModel.h" +#include "Numeric.h" +#include "Context.h" +#include "Parser.h" +#include "OpenFile.h" +#include "CommandLine.h" +#include "Views.h" +#include "ReadImg.h" +#include "OS.h" +#include "HighOrder.h" + +#if defined(HAVE_FLTK) +#include "GmshUI.h" +#include "Draw.h" +#include "SelectBuffer.h" +#include "GUI.h" +extern GUI *WID; +void UpdateViewsInGUI(); +#endif + +extern Mesh *THEM; +extern GModel *GMODEL; +extern Context_T CTX; + +void FixRelativePath(char *in, char *out){ + if(in[0] == '/' || in[0] == '\\' || (strlen(in)>2 && in[1] == ':')){ + // do nothing: 'in' is an absolute path + strcpy(out, in); + } + else{ + // append 'in' to the path of the parent file + strcpy(out, yyname); + int i = strlen(out)-1 ; + while(i >= 0 && yyname[i] != '/' && yyname[i] != '\\') i-- ; + out[i+1] = '\0'; + strcat(out, in); + } +} + +void FixWindowsPath(char *in, char *out){ +#if defined(__CYGWIN__) + cygwin_conv_to_win32_path(in, out); +#else + strcpy(out, in); +#endif +} + +void SplitFileName(char *name, char *base, char *ext) +{ + strcpy(base, name); + strcpy(ext, ""); + for(int i = strlen(name)-1; i >= 0; i--){ + if(name[i] == '.'){ + strcpy(ext, &name[i]); + base[i] = '\0'; + break; + } + } +} + +static void FinishUpBoundingBox() +{ + double range[3]; + + for(int i = 0; i < 3; i++){ + CTX.cg[i] = 0.5 * (CTX.min[i] + CTX.max[i]); + range[i] = CTX.max[i] - CTX.min[i]; + } + + if(range[0] == 0. && range[1] == 0. && range[2] == 0.) { + CTX.min[0] -= 1.; CTX.min[1] -= 1.; + CTX.max[0] += 1.; CTX.max[1] += 1.; + CTX.lc = 1.; + } + else if(range[0] == 0. && range[1] == 0.) { + CTX.lc = range[2]; + CTX.min[0] -= CTX.lc; CTX.min[1] -= CTX.lc; + CTX.max[0] += CTX.lc; CTX.max[1] += CTX.lc; + } + else if(range[0] == 0. && range[2] == 0.) { + CTX.lc = range[1]; + CTX.min[0] -= CTX.lc; CTX.max[0] += CTX.lc; + } + else if(range[1] == 0. && range[2] == 0.) { + CTX.lc = range[0]; + CTX.min[1] -= CTX.lc; CTX.max[1] += CTX.lc; + } + else if(range[0] == 0.) { + CTX.lc = sqrt(DSQR(range[1]) + DSQR(range[2])); + CTX.min[0] -= CTX.lc; CTX.max[0] += CTX.lc; + } + else if(range[1] == 0.) { + CTX.lc = sqrt(DSQR(range[0]) + DSQR(range[2])); + CTX.min[1] -= CTX.lc; CTX.max[1] += CTX.lc; + } + else if(range[2] == 0.) { + CTX.lc = sqrt(DSQR(range[0]) + DSQR(range[1])); + } + else { + CTX.lc = sqrt(DSQR(range[0]) + DSQR(range[1]) + DSQR(range[2])); + } +} + +void SetBoundingBox(double xmin, double xmax, + double ymin, double ymax, + double zmin, double zmax) +{ + CTX.min[0] = xmin; CTX.max[0] = xmax; + CTX.min[1] = ymin; CTX.max[1] = ymax; + CTX.min[2] = zmin; CTX.max[2] = zmax; + FinishUpBoundingBox(); +} + +void SetBoundingBox(void) +{ + if(CTX.forced_bbox) return; + + SBoundingBox3d bb; + + bb = GMODEL->bounds(); + + if(bb.empty() && List_Nbr(CTX.post.list)) { + for(int i = 0; i < List_Nbr(CTX.post.list); i++){ + Post_View *v = *(Post_View **)List_Pointer(CTX.post.list, i); + if(fabs(v->BBox[0]) != VAL_INF && + fabs(v->BBox[2]) != VAL_INF && + fabs(v->BBox[4]) != VAL_INF) + bb += SPoint3(v->BBox[0], v->BBox[2], v->BBox[4]); + if(fabs(v->BBox[1]) != VAL_INF && + fabs(v->BBox[3]) != VAL_INF && + fabs(v->BBox[5]) != VAL_INF) + bb += SPoint3(v->BBox[1], v->BBox[3], v->BBox[5]); + } + } + + if(bb.empty()){ + bb += SPoint3(-1., -1., -1.); + bb += SPoint3(1., 1., 1.); + } + + CTX.min[0] = bb.min().x(); CTX.max[0] = bb.max().x(); + CTX.min[1] = bb.min().y(); CTX.max[1] = bb.max().y(); + CTX.min[2] = bb.min().z(); CTX.max[2] = bb.max().z(); + FinishUpBoundingBox(); +} + +// FIXME: this is necessary for now to have an approximate CTX.lc +// *while* parsing input files (it's important since some of the +// geometrical operations use a tolerance that depends on +// CTX.lc). This will be removed once the new database is filled +// directly during the parsing step +static SBoundingBox3d temp_bb; + +void ResetTemporaryBoundingBox() +{ + temp_bb.reset(); +} + +void AddToTemporaryBoundingBox(double x, double y, double z) +{ + temp_bb += SPoint3(x, y, z); + CTX.min[0] = temp_bb.min().x(); CTX.max[0] = temp_bb.max().x(); + CTX.min[1] = temp_bb.min().y(); CTX.max[1] = temp_bb.max().y(); + CTX.min[2] = temp_bb.min().z(); CTX.max[2] = temp_bb.max().z(); + FinishUpBoundingBox(); +} + +int ParseFile(char *f, int close, int warn_if_missing) +{ + char yyname_old[256], tmp[256]; + FILE *yyin_old, *fp; + int yylineno_old, yyerrorstate_old, numviews_old; + + // add 'b' for pure Windows programs: opening in text mode messes up + // fsetpos/fgetpos (used e.g. for user-defined functions) + if(!(fp = fopen(f, "rb"))){ + if(warn_if_missing) Msg(WARNING, "Unable to open file '%s'", f); + return 0; + } + + strncpy(yyname_old, yyname, 255); + yyin_old = yyin; + yyerrorstate_old = yyerrorstate; + yylineno_old = yylineno; + numviews_old = List_Nbr(CTX.post.list); + + strncpy(yyname, f, 255); + yyin = fp; + yyerrorstate = 0; + yylineno = 1; + + fpos_t position; + fgetpos(yyin, &position); + fgets(tmp, sizeof(tmp), yyin); + fsetpos(yyin, &position); + + while(!feof(yyin)){ + yyparse(); + if(yyerrorstate > 20){ + Msg(GERROR, "Too many errors: aborting..."); + force_yyflush(); + break; + } + } + + if(close) + fclose(yyin); + + strncpy(yyname, yyname_old, 255); + yyin = yyin_old; + yyerrorstate = yyerrorstate_old; + yylineno = yylineno_old; + + if(List_Nbr(CTX.post.list) != numviews_old){ +#if defined(HAVE_FLTK) + UpdateViewsInGUI(); +#endif + } + + return 1; +} + +void ParseString(char *str) +{ + if(!str) return; + FILE *fp; + if((fp = fopen(CTX.tmp_filename_fullpath, "w"))) { + fprintf(fp, str); + fprintf(fp, "\n"); + fclose(fp); + ParseFile(CTX.tmp_filename_fullpath, 1); + if(GMODEL) GMODEL->importTHEM(); + } +} + +void SetProjectName(char *name) +{ + char base[356], ext[256]; + SplitFileName(name, base, ext); + + strncpy(CTX.filename, name, 255); + strncpy(CTX.base_filename, base, 255); + +#if defined(HAVE_FLTK) + if(!CTX.batch) WID->set_title(CTX.filename); +#endif +} + +int MergeFile(char *name, int warn_if_missing) +{ + // FIXME: to be removed + // #if defined(HAVE_FOURIER_MODEL) + // if(!strcmp(name, "falcon") || !strcmp(name, "ship")){ + // GMODEL->readFourier(name); + // SetBoundingBox(); + // CTX.mesh.changed = ENT_ALL; + // return 1; + // } + // #endif + + // added 'b' for pure Windows programs, since some of these files + // contain binary data + FILE *fp = fopen(name, "rb"); + if(!fp){ + if(warn_if_missing) Msg(WARNING, "Unable to open file '%s'", name); + return 0; + } + + char header[256]; + fgets(header, sizeof(header), fp); + fclose(fp); + + Msg(STATUS2, "Reading '%s'", name); + + char ext[256], base[256]; + SplitFileName(name, base, ext); + +#if defined(HAVE_FLTK) + if(!CTX.batch) { + if(!strcmp(ext, ".gz")) { + // the real solution would be to rewrite all our I/O functions in + // terms of gzFile, but until then, this is better than nothing + if(fl_choice("File '%s' is in gzip format.\n\nDo you want to uncompress it?", + "Cancel", "Uncompress", NULL, name)){ + char tmp[256]; + sprintf(tmp, "gunzip -c %s > %s", name, base); + SystemCall(tmp); + if(!strcmp(CTX.filename, name)) // this is the project file + SetProjectName(base); + return MergeFile(base); + } + } + } +#endif + + CTX.geom.draw = 0; // don't try to draw the model while reading + int status = 0; + if(!strcmp(ext, ".stl") || !strcmp(ext, ".STL")){ + status = GMODEL->readSTL(name, CTX.geom.tolerance); + } + else if(!strcmp(ext, ".brep") || !strcmp(ext, ".rle") || + !strcmp(ext, ".brp") || !strcmp(ext, ".BRP")){ + GMODEL->readOCCBREP(std::string(name)); + } + else if(!strcmp(ext, ".iges") || !strcmp(ext, ".IGES") || + !strcmp(ext, ".igs") || !strcmp(ext, ".IGS")){ + GMODEL->readOCCIGES(std::string(name)); + } + else if(!strcmp(ext, ".step") || !strcmp(ext, ".STEP") || + !strcmp(ext, ".stp") || !strcmp(ext, ".STP")){ + GMODEL->readOCCSTEP(std::string(name)); + } + else if(!strcmp(ext, ".unv") || !strcmp(ext, ".UNV")){ + status = GMODEL->readUNV(name); + } + else if(!strcmp(ext, ".wrl") || !strcmp(ext, ".WRL") || + !strcmp(ext, ".vrml") || !strcmp(ext, ".VRML") || + !strcmp(ext, ".iv") || !strcmp(ext, ".IV")){ + status = GMODEL->readVRML(name); + } + else if(!strcmp(ext, ".mesh") || !strcmp(ext, ".MESH")){ + status = GMODEL->readMESH(name); + } + else if(!strcmp(ext, ".bdf") || !strcmp(ext, ".BDF") || + !strcmp(ext, ".nas") || !strcmp(ext, ".NAS")){ + status = GMODEL->readBDF(name); + } + else if(!strcmp(ext, ".p3d") || !strcmp(ext, ".P3D")){ + status = GMODEL->readP3D(name); + } + else if(!strcmp(ext, ".fm") || !strcmp(ext, ".FM")) { + status = GMODEL->readF(name); + } +#if defined(HAVE_FLTK) + else if(!strcmp(ext, ".pnm") || !strcmp(ext, ".PNM") || + !strcmp(ext, ".pbm") || !strcmp(ext, ".PBM") || + !strcmp(ext, ".pgm") || !strcmp(ext, ".PGM") || + !strcmp(ext, ".ppm") || !strcmp(ext, ".PPM")) { + status = read_pnm(name); + } + else if(!strcmp(ext, ".bmp") || !strcmp(ext, ".BMP")) { + status = read_bmp(name); + } +#if defined(HAVE_LIBJPEG) + else if(!strcmp(ext, ".jpg") || !strcmp(ext, ".JPG") || + !strcmp(ext, ".jpeg") || !strcmp(ext, ".JPEG")) { + status = read_jpeg(name); + } +#endif +#if defined(HAVE_LIBPNG) + else if(!strcmp(ext, ".png") || !strcmp(ext, ".PNG")) { + status = read_png(name); + } +#endif +#endif + else { + CTX.geom.draw = 1; + if(!strncmp(header, "$PTS", 4) || !strncmp(header, "$NO", 3) || + !strncmp(header, "$PARA", 5) || !strncmp(header, "$ELM", 4) || + !strncmp(header, "$MeshFormat", 11)) { + status = GMODEL->readMSH(name); + } + else if(!strncmp(header, "$PostFormat", 11) || + !strncmp(header, "$View", 5)) { + status = ReadView(name); + } + else { + status = GMODEL->readGEO(name); + } + } + + SetBoundingBox(); + + CTX.geom.draw = 1; + CTX.mesh.changed = ENT_ALL; + + checkHighOrderTriangles ( GMODEL ); + + Msg(STATUS2, "Read '%s'", name); + return status; +} + +void OpenProject(char *name) +{ + if(CTX.threads_lock) { + Msg(INFO, "I'm busy! Ask me that later..."); + return; + } + CTX.threads_lock = 1; + + GMODEL->destroy(); + THEM->destroy(); + + // Initialize pseudo random mesh generator to the same seed + srand(1); + + // temporary hack until we fill GMODEL on the fly during parsing + ResetTemporaryBoundingBox(); + + SetProjectName(name); + MergeFile(name); + + CTX.threads_lock = 0; + +#if defined(HAVE_FLTK) + if(!CTX.batch) WID->reset_visibility(); + ZeroHighlight(); +#endif +} + +void OpenProjectMacFinder(const char *filename) +{ + static int first = 1; + if(first || CTX.batch){ + // just copy the filename: it will be opened when the GUI is ready + // in main() + strncpy(CTX.filename, filename, 255); + first = 0; + } + else{ + OpenProject((char*)filename); +#if defined(HAVE_FLTK) + Draw(); +#endif + } +} + diff --git a/configure b/configure index 22b61a37ca..fe6706e2e5 100755 --- a/configure +++ b/configure @@ -866,6 +866,7 @@ Optional Features: --enable-cgns enable CGNS output (default=no) --enable-occ enable OpenCascade support (default=no) --enable-med enable MED support (default=yes) + --enable-fm enable support for Fourier models (default=yes) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -1485,6 +1486,11 @@ fi; if test "${enable_med+set}" = set; then enableval="$enable_med" +fi; +# Check whether --enable-fm or --disable-fm was given. +if test "${enable_fm+set}" = set; then + enableval="$enable_fm" + fi; UNAME=`uname` @@ -4246,6 +4252,7 @@ fi fi fi + if test "x$enable_matheval" != "xno"; then echo "$as_me:$LINENO: checking for ./contrib/MathEval/matheval.cpp" >&5 echo $ECHO_N "checking for ./contrib/MathEval/matheval.cpp... $ECHO_C" >&6 if test "${ac_cv_file___contrib_MathEval_matheval_cpp+set}" = set; then @@ -4269,43 +4276,43 @@ else MATHEVAL="no" fi - if test "x${MATHEVAL}" = "xyes"; then - if test "x$enable_matheval" != "xno"; then - GMSH_DIRS="${GMSH_DIRS} contrib/MathEval" - GMSH_LIBS="${GMSH_LIBS} -lGmshMathEval" - FLAGS="-DHAVE_MATH_EVAL ${FLAGS}" + if test "x${MATHEVAL}" = "xyes"; then + GMSH_DIRS="${GMSH_DIRS} contrib/MathEval" + GMSH_LIBS="${GMSH_LIBS} -lGmshMathEval" + FLAGS="-DHAVE_MATH_EVAL ${FLAGS}" fi fi - echo "$as_me:$LINENO: checking for ./contrib/FourierModel/model.cpp" >&5 -echo $ECHO_N "checking for ./contrib/FourierModel/model.cpp... $ECHO_C" >&6 -if test "${ac_cv_file___contrib_FourierModel_model_cpp+set}" = set; then + if test "x$enable_fm" != "xno"; then + echo "$as_me:$LINENO: checking for ./contrib/FourierModel/FM_Face.cpp" >&5 +echo $ECHO_N "checking for ./contrib/FourierModel/FM_Face.cpp... $ECHO_C" >&6 +if test "${ac_cv_file___contrib_FourierModel_FM_Face_cpp+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else test "$cross_compiling" = yes && { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5 echo "$as_me: error: cannot check for file existence when cross compiling" >&2;} { (exit 1); exit 1; }; } -if test -r "./contrib/FourierModel/model.cpp"; then - ac_cv_file___contrib_FourierModel_model_cpp=yes +if test -r "./contrib/FourierModel/FM_Face.cpp"; then + ac_cv_file___contrib_FourierModel_FM_Face_cpp=yes else - ac_cv_file___contrib_FourierModel_model_cpp=no + ac_cv_file___contrib_FourierModel_FM_Face_cpp=no fi fi -echo "$as_me:$LINENO: result: $ac_cv_file___contrib_FourierModel_model_cpp" >&5 -echo "${ECHO_T}$ac_cv_file___contrib_FourierModel_model_cpp" >&6 -if test $ac_cv_file___contrib_FourierModel_model_cpp = yes; then +echo "$as_me:$LINENO: result: $ac_cv_file___contrib_FourierModel_FM_Face_cpp" >&5 +echo "${ECHO_T}$ac_cv_file___contrib_FourierModel_FM_Face_cpp" >&6 +if test $ac_cv_file___contrib_FourierModel_FM_Face_cpp = yes; then FOURIER="yes" else FOURIER="no" fi - if test "x${FOURIER}" = "xyes"; then - GMSH_DIRS="${GMSH_DIRS} contrib/FourierModel" - GMSH_LIBS="${GMSH_LIBS} -lGmshFourierModel" - FLAGS="-DHAVE_FOURIER_MODEL ${FLAGS}" + if test "x${FOURIER}" = "xyes"; then + GMSH_DIRS="${GMSH_DIRS} contrib/FourierModel" + GMSH_LIBS="${GMSH_LIBS} -lGmshFourierModel" + FLAGS="-DHAVE_FOURIER_MODEL ${FLAGS}" + fi fi - fi if test "x$enable_gsl" != "xno"; then diff --git a/configure.in b/configure.in index c6f6c192c6..6d1190baa4 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -dnl $Id: configure.in,v 1.124 2007-03-29 16:34:21 geuzaine Exp $ +dnl $Id: configure.in,v 1.125 2007-05-03 08:50:01 geuzaine Exp $ dnl dnl Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle dnl @@ -125,6 +125,9 @@ AC_ARG_ENABLE(occ, AC_ARG_ENABLE(med, AC_HELP_STRING([--enable-med], [enable MED support (default=yes)])) +AC_ARG_ENABLE(fm, + AC_HELP_STRING([--enable-fm], + [enable support for Fourier models (default=yes)])) dnl Get the operating system name UNAME=`uname` @@ -475,23 +478,24 @@ if test "x$enable_contrib" != "xno"; then fi dnl Check for MathEval - AC_CHECK_FILE(./contrib/MathEval/matheval.cpp, MATHEVAL="yes", MATHEVAL="no") - if test "x${MATHEVAL}" = "xyes"; then - if test "x$enable_matheval" != "xno"; then - GMSH_DIRS="${GMSH_DIRS} contrib/MathEval" - GMSH_LIBS="${GMSH_LIBS} -lGmshMathEval" - FLAGS="-DHAVE_MATH_EVAL ${FLAGS}" + if test "x$enable_matheval" != "xno"; then + AC_CHECK_FILE(./contrib/MathEval/matheval.cpp, MATHEVAL="yes", MATHEVAL="no") + if test "x${MATHEVAL}" = "xyes"; then + GMSH_DIRS="${GMSH_DIRS} contrib/MathEval" + GMSH_LIBS="${GMSH_LIBS} -lGmshMathEval" + FLAGS="-DHAVE_MATH_EVAL ${FLAGS}" fi fi dnl Check for FourierModel - AC_CHECK_FILE(./contrib/FourierModel/model.cpp, FOURIER="yes", FOURIER="no") - if test "x${FOURIER}" = "xyes"; then - GMSH_DIRS="${GMSH_DIRS} contrib/FourierModel" - GMSH_LIBS="${GMSH_LIBS} -lGmshFourierModel" - FLAGS="-DHAVE_FOURIER_MODEL ${FLAGS}" + if test "x$enable_fm" != "xno"; then + AC_CHECK_FILE(./contrib/FourierModel/FM_Face.cpp, FOURIER="yes", FOURIER="no") + if test "x${FOURIER}" = "xyes"; then + GMSH_DIRS="${GMSH_DIRS} contrib/FourierModel" + GMSH_LIBS="${GMSH_LIBS} -lGmshFourierModel" + FLAGS="-DHAVE_FOURIER_MODEL ${FLAGS}" + fi fi - fi dnl Check for GSL diff --git a/contrib/FourierModel/ContinuationPatch.cpp b/contrib/FourierModel/ContinuationPatch.cpp new file mode 100644 index 0000000000..8018987703 --- /dev/null +++ b/contrib/FourierModel/ContinuationPatch.cpp @@ -0,0 +1,500 @@ +#include <math.h> +#include "Message.h" +#include "ContinuationPatch.h" + +ContinuationPatch::ContinuationPatch(PatchInfo *PI, int derivative) : Patch(PI) +{ + _NcrossT[0] = _PI->normal[1] * _PI->tangent[2] - + _PI->normal[2] * _PI->tangent[1]; + _NcrossT[1] = _PI->normal[2] * _PI->tangent[0] - + _PI->normal[0] * _PI->tangent[2]; + _NcrossT[2] = _PI->normal[0] * _PI->tangent[1] - + _PI->normal[1] * _PI->tangent[0]; + + _derivative = derivative; + + _uModes = _PI->nModes[0]; + _vModes = _PI->nModes[1]; + + _periodU = (1-_PI->periodic[0]) + 1; + _periodV = (1-_PI->periodic[1]) + 1; + + //Msg::Info("Period : %g %g",_periodU,_periodV); + + if ((_uModes % 2) == 0) { + _uModesLower = - _uModes/2; + _uModesUpper = _uModes/2 - 1; + } + else { + _uModesLower = - (_uModes - 1)/2; + _uModesUpper = (_uModes - 1)/2; + } + if ((_vModes % 2) == 0) { + _vModesLower = - _vModes/2; + _vModesUpper = _vModes/2 - 1; + } + else { + _vModesLower = - (_vModes - 1)/2; + _vModesUpper = (_vModes - 1)/2; + } + + // Initialize Data + _coeffData = new std::complex<double>*[_uModes]; + for(int j = 0; j < _uModes; j++){ + _coeffData[j] = new std::complex<double>[_vModes]; + for(int k = 0; k < _vModes; k++) + _coeffData[j][k] = _PI->coeff[j][k]; + } + + // Check if we need to interpolate the derivative(s) + if(_derivative){ + // Initialize _fineDeriv and _fineDeriv2 to zero + if(_derivative & 1){ + _coeffDerivU = new std::complex<double>*[_uModes]; + _coeffDerivV = new std::complex<double>*[_uModes]; + for(int j = 0; j < _uModes; j++){ + _coeffDerivU[j] = new std::complex<double>[_vModes]; + _coeffDerivV[j] = new std::complex<double>[_vModes]; + for(int k = 0; k < _vModes; k++){ + _coeffDerivU[j][k] = 0.; + _coeffDerivV[j][k] = 0.; + } + } + } + + if(_derivative & 2){ + _coeffDerivUU = new std::complex<double>*[_uModes]; + _coeffDerivVV = new std::complex<double>*[_uModes]; + _coeffDerivUV = new std::complex<double>*[_uModes]; + for(int j = 0; j < _uModes; j++){ + _coeffDerivUU[j] = new std::complex<double>[_vModes]; + _coeffDerivVV[j] = new std::complex<double>[_vModes]; + _coeffDerivUV[j] = new std::complex<double>[_vModes]; + for(int k = 0; k < _vModes; k++){ + _coeffDerivUU[j][k] = 0.; + _coeffDerivVV[j][k] = 0.; + _coeffDerivUV[j][k] = 0.; + } + } + } + + // Copy the Fourier coefficients into _coeffDeriv and _coeffDeriv2 + std::complex<double> I(0., 1.); + for(int j = 0; j < _uModes; j++){ + for(int k = 0; k < _vModes; k++){ + int J = j+_uModesLower; + int K = k+_vModesLower; + if(_derivative & 1){ + _coeffDerivU[j][k] = (2 * M_PI * J * I / _periodU) *_coeffData[j][k]; + _coeffDerivV[j][k] = (2 * M_PI * K * I / _periodV) *_coeffData[j][k]; + } + if(_derivative & 2){ + _coeffDerivUU[j][k] = - (4 * M_PI * M_PI * J * J / + (_periodU * _periodU)) * _coeffData[j][k]; + _coeffDerivVV[j][k] = - (4 * M_PI * M_PI * K * K / + (_periodV * _periodV)) * _coeffData[j][k]; + _coeffDerivUV[j][k] = - (4 * M_PI * M_PI * J * K / + (_periodU * _periodV)) * _coeffData[j][k]; + } + } + } + } + // Initialize interpolation variables + _tmpCoeff = std::vector< std::complex<double> >(_vModes); + _tmpInterp = std::vector< std::complex<double> >(_uModes); +} + +ContinuationPatch::~ContinuationPatch() +{ + for(int j = 0; j < _uModes; j++) + delete [] _coeffData[j]; + delete [] _coeffData; + + if(_coeffDerivU){ + for(int j = 0; j < _uModes; j++) + delete [] _coeffDerivU[j]; + delete [] _coeffDerivU; + } + if(_coeffDerivV){ + for(int j = 0; j < _uModes; j++) + delete [] _coeffDerivV[j]; + delete [] _coeffDerivV; + } + if(_coeffDerivUU){ + for(int j = 0; j < _uModes; j++) + delete [] _coeffDerivUU[j]; + delete [] _coeffDerivUU; + } + if(_coeffDerivVV){ + for(int j = 0; j < _uModes; j++) + delete [] _coeffDerivVV[j]; + delete [] _coeffDerivVV; + } + if(_coeffDerivUV){ + for(int j = 0; j < _uModes; j++) + delete [] _coeffDerivUV[j]; + delete [] _coeffDerivUV; + } +} + +std::complex<double> ContinuationPatch:: +_PolyEval(std::vector< std::complex<double> > _coeff, std::complex<double> x) +{ + int _polyOrder = _coeff.size()-1; + std::complex<double> out = 0.; + + out = x * _coeff[_polyOrder]; + for (int i = _polyOrder - 1; i > 0; i--) + out = x * (out + _coeff[i]); + out = out + _coeff[0]; + + return out; +} + +std::complex<double> ContinuationPatch:: + _Interpolate(double u, double v, int uDer, int vDer) +{ + //Msg::Info("%d %d %d",uDer,vDer,_derivative); + if (((uDer==2 || vDer==2 || (uDer==1 && vDer==1)) && !(_derivative & 2) ) || + ((uDer==1 || vDer==1) && !(_derivative & 1)) || + (uDer<0 || uDer>2 || vDer<0 || vDer>2) ) { + Msg::Error("Derivative data not available: check contructor call %d %d %d", + uDer,vDer,_derivative); + return 0.; + } + + double epsilon = 1e-12; + if(u < 0. - epsilon || u > 1. + epsilon){ + Msg::Error("Trying to interpolate outside interval: (u,v)=(%.16g,%.16g) " + "not in [%g,%g]x[%g,%g]", u, v, 0., 1., 0., 1.); + } + + // Interpolate to find value at (u,v) + for(int j = 0; j < _uModes; j++){ + for(int k = 0; k < _vModes; k++){ + std::complex<double> tmp; + if(uDer == 0 && vDer == 0) + tmp = _coeffData[j][k]; + else if(uDer == 1 && vDer == 0) + tmp = _coeffDerivU[j][k]; + else if(uDer == 0 && vDer == 1) + tmp = _coeffDerivV[j][k]; + else if(uDer == 2 && vDer == 0) + tmp = _coeffDerivUU[j][k]; + else if(uDer == 0 && vDer == 2) + tmp = _coeffDerivVV[j][k]; + else + tmp = _coeffDerivUV[j][k]; + _tmpCoeff[k] = tmp; + } + std::complex<double> y(cos(2 * M_PI * v / _periodV), + sin(2 * M_PI * v / _periodV)); + _tmpInterp[j] = _PolyEval(_tmpCoeff, y); + _tmpInterp[j] *= std::complex<double> + (cos(2 * M_PI * _vModesLower * v / _periodV), + sin(2 * M_PI * _vModesLower * v / _periodV)); + } + std::complex<double> x(cos(2 * M_PI * u / _periodU), + sin(2 * M_PI * u / _periodU)); + return _PolyEval(_tmpInterp, x) * std::complex<double> + (cos(2 * M_PI * _uModesLower * u / _periodU), + sin(2 * M_PI * _uModesLower * u / _periodU)); +} + +void ContinuationPatch::P(double u, double v, double &x, double &y, double &z, + double &nx, double &ny, double &nz) +{ + if (!strcmp(_PI->projection,"cylinder")) { + x = _PI->origin[0] + _PI->normal[0] * _PI->scale[1] * v; + y = _PI->origin[1] + _PI->normal[1] * _PI->scale[1] * v; + z = _PI->origin[2] + _PI->normal[2] * _PI->scale[1] * v; + + nx = _PI->tangent[0] * cos(_PI->scale[0] * (u - 0.5)) + + _NcrossT[0] * sin(_PI->scale[0] * (u - 0.5)); + ny = _PI->tangent[1] * cos(_PI->scale[0] * (u - 0.5)) + + _NcrossT[1] * sin(_PI->scale[0] * (u - 0.5)); + nz = _PI->tangent[2] * cos(_PI->scale[0] * (u - 0.5)) + + _NcrossT[2] * sin(_PI->scale[0] * (u - 0.5)); + + double norm = sqrt(nx * nx + ny * ny + nz * nz); + nx /= norm; + ny /= norm; + nz /= norm; + } + else if (!strcmp(_PI->projection,"cylinder")) { + x = y = z = nx = ny = nz = 0; + } + else { + Msg::Info("Unknown projection surface"); + x = y = z = nx = ny = nz = 0; + } +} + +bool ContinuationPatch::pInverse(double x,double y,double z, + double &u,double &v) +{ + if (!strcmp(_PI->projection,"cylinder")) { + double t = (x - _PI->origin[0]) * _PI->normal[0] + + (y - _PI->origin[1]) * _PI->normal[1] + + (z - _PI->origin[2]) * _PI->normal[2]; + v = t / _PI->scale[1]; + double n[3]; + n[0] = x - (_PI->origin[0] + t * _PI->normal[0]); + n[1] = y - (_PI->origin[1] + t * _PI->normal[1]); + n[2] = z - (_PI->origin[2] + t * _PI->normal[2]); + double norm = sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]); + for (int i=0;i<3;i++) + n[i] /= norm; + u = atan2((n[0]*_NcrossT[0]+n[1]*_NcrossT[1]+n[2]*_NcrossT[2]), + (n[0]*_PI->tangent[0]+n[1]*_PI->tangent[1]+ + n[2]*_PI->tangent[2])); + u /= _PI->scale[0]; + u += 0.5; + + } + else if (!strcmp(_PI->projection,"cylinder")) { + u = v = 0.; + } + else { + Msg::Info("Unknown projection surface"); + u = v = 0.; + } +} + +void ContinuationPatch::Dpdu(double u, double v, + double &x, double &y, double &z, + double &nx, double &ny, double &nz) +{ + if (!strcmp(_PI->projection,"cylinder")) { + x = y = z = 0.; + + double n[3], nu[3]; + for (int i=0;i<3;i++) { + n[i] = _PI->tangent[i] * cos(_PI->scale[0] * u) + + _NcrossT[i] * sin(_PI->scale[0] * u); + nu[i] = _PI->scale[0] * (- _PI->tangent[i] * sin(_PI->scale[0] * u) + + _NcrossT[i] * cos(_PI->scale[0] * u)); + } + double norm = sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]); + double NdotNu = n[0] * nu[0] + n[1] * nu[1] + n[2] * nu[2]; + nx = nu[0] / norm - NdotNu * n[0] / (norm * norm * norm); + ny = nu[1] / norm - NdotNu * n[1] / (norm * norm * norm); + nz = nu[2] / norm - NdotNu * n[2] / (norm * norm * norm); + } + else if (!strcmp(_PI->projection,"cylinder")) { + x = y = z = nx = ny = nz = 0; + } + else { + Msg::Info("Unknown projection surface"); + x = y = z = nx = ny = nz = 0; + } +} + +void ContinuationPatch::Dpdv(double u, double v, + double &x, double &y, double &z, + double &nx, double &ny, double &nz) +{ + if (!strcmp(_PI->projection,"cylinder")) { + x = _PI->normal[0] * _PI->scale[1]; + y = _PI->normal[1] * _PI->scale[1]; + z = _PI->normal[2] * _PI->scale[1]; + + nx = ny = nz = 0.; + } + else if (!strcmp(_PI->projection,"cylinder")) { + x = y = z = nx = ny = nz = 0; + } + else { + Msg::Info("Unknown projection surface"); + x = y = z = nx = ny = nz = 0; + } +} + +void ContinuationPatch::Dpdpdudu(double u,double v, + double &x, double &y, double &z, + double &nx, double &ny, double &nz) +{ + if (!strcmp(_PI->projection,"cylinder")) { + x = y = z = 0.; + double n[3], nu[3], nuu[3]; + for (int i=0;i<3;i++) { + n[i] = _PI->tangent[i] * cos(_PI->scale[0] * (u-0.5)) + + _NcrossT[i] * sin(_PI->scale[0] * (u-0.5)); + nu[i] = _PI->scale[0] * + (- _PI->tangent[i] * sin(_PI->scale[0] * (u-0.5)) + + _NcrossT[i] * cos(_PI->scale[0] * (u-0.5))); + nuu[i] = - _PI->scale[0] * _PI->scale[0] * + (_PI->tangent[i] * cos(_PI->scale[0] * (u-0.5)) + + _NcrossT[i] * sin(_PI->scale[0] * (u-0.5))); + } + double norm = sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]); + double NdotNu = n[0] * nu[0] + n[1] * nu[1] + n[2] * nu[2]; + double NudotNu = nu[0] * nu[0] + nu[1] * nu[1] + nu[2] * nu[2]; + double NdotNuu = n[0] * nuu[0] + n[1] * nuu[1] + n[2] * nuu[2]; + + nx = nuu[0] / norm - (NdotNu * nu[0] + (NdotNuu + NudotNu) * n[0] + + NdotNu * nu[0]) / (norm * norm * norm) + + 3 * NdotNu * NdotNu * n[0] / (norm * norm * norm * norm * norm); + ny = nuu[1] / norm - (NdotNu * nu[1] + (NdotNuu + NudotNu) * n[1] + + NdotNu * nu[1]) / (norm * norm * norm) + + 3 * NdotNu * NdotNu * n[1] / (norm * norm * norm * norm * norm); + nz = nuu[2] / norm - (NdotNu * nu[2] + (NdotNuu + NudotNu) * n[2] + + NdotNu * nu[2]) / (norm * norm * norm) + + 3 * NdotNu * NdotNu * n[2] / (norm * norm * norm * norm * norm); + } + else if (!strcmp(_PI->projection,"cylinder")) { + x = y = z = nx = ny = nz = 0; + } + else { + Msg::Info("Unknown projection surface"); + x = y = z = nx = ny = nz = 0; + } +} + +void ContinuationPatch::Dpdpdudv(double u, double v, + double &x, double &y, double &z, + double &nx, double &ny, double &nz) +{ + if (!strcmp(_PI->projection,"cylinder")) { + x = y = z = nx = ny = nz = 0.; + } + else if (!strcmp(_PI->projection,"cylinder")) { + x = y = z = nx = ny = nz = 0; + } + else { + Msg::Info("Unknown projection surface"); + x = y = z = nx = ny = nz = 0; + } +} + +void ContinuationPatch::Dpdpdvdv(double u, double v, + double &x, double &y, double &z, + double &nx, double &ny, double &nz) +{ + if (!strcmp(_PI->projection,"cylinder")) { + x = y = z = nx = ny = nz = 0.; + } + else if (!strcmp(_PI->projection,"cylinder")) { + x = y = z = nx = ny = nz = 0; + } + else { + Msg::Info("Unknown projection surface"); + x = y = z = nx = ny = nz = 0; + } +} + +void ContinuationPatch:: +F(double u, double v, double &x, double &y, double &z) +{ + double px, py, pz, nx, ny, nz, d; + P(u,v,px,py,pz,nx,ny,nz); + d = _Interpolate(u, v, 0, 0).real(); + x = px + d * nx; + y = py + d * ny; + z = pz + d * nz; +} + +bool ContinuationPatch:: +Inverse(double x,double y,double z,double &u,double &v) +{ + pInverse(x,y,z,u,v); +} + +void ContinuationPatch:: +Dfdu(double u, double v, double &x, double &y, double &z) +{ + double px, py, pz, nx, ny, nz, d; + double pxu, pyu, pzu, nxu, nyu, nzu, du; + P(u,v,px,py,pz,nx,ny,nz); + Dpdu(u,v,pxu,pyu,pzu,nxu,nyu,nzu); + d = _Interpolate(u, v, 0, 0).real(); + du = _Interpolate(u, v, 1, 0).real(); + + x = pxu + du * nx + d * nxu; + y = pyu + du * ny + d * nyu; + z = pzu + du * nz + d * nzu; +} + +void ContinuationPatch:: +Dfdv(double u, double v, double &x, double &y, double &z) +{ + double px, py, pz, nx, ny, nz, d; + double pxv, pyv, pzv, nxv, nyv, nzv, dv; + P(u,v,px,py,pz,nx,ny,nz); + Dpdu(u,v,pxv,pyv,pzv,nxv,nyv,nzv); + d = _Interpolate(u, v, 0, 0).real(); + dv = _Interpolate(u, v, 0, 1).real(); + + x = pxv + dv * nx + d * nxv; + y = pyv + dv * ny + d * nyv; + z = pzv + dv * nz + d * nzv; +} + +void ContinuationPatch:: +Dfdfdudu(double u, double v, double &x, double &y, double &z) +{ + double px, py, pz, nx, ny, nz, d; + double pxu, pyu, pzu, nxu, nyu, nzu, du; + double pxuu, pyuu, pzuu, nxuu, nyuu, nzuu, duu; + + P(u,v,px,py,pz,nx,ny,nz); + Dpdu(u,v,pxu,pyu,pzu,nxu,nyu,nzu); + Dpdpdudu(u,v,pxuu,pyuu,pzuu,nxuu,nyuu,nzuu); + + d = _Interpolate(u, v, 0, 0).real(); + du = _Interpolate(u, v, 1, 0).real(); + duu = _Interpolate(u, v, 2, 0).real(); + + x = pxuu + duu * nx + du * nxu + du * nxu + d * nxuu; + y = pyuu + duu * ny + du * nyu + du * nyu + d * nyuu; + z = pzuu + duu * nz + du * nzu + du * nzu + d * nzuu; +} + +void ContinuationPatch:: +Dfdfdvdv(double u, double v, double &x, double &y, double &z) +{ + double px, py, pz, nx, ny, nz, d; + double pxv, pyv, pzv, nxv, nyv, nzv, dv; + double pxvv, pyvv, pzvv, nxvv, nyvv, nzvv, dvv; + + P(u,v,px,py,pz,nx,ny,nz); + Dpdv(u,v,pxv,pyv,pzv,nxv,nyv,nzv); + Dpdpdvdv(u,v,pxvv,pyvv,pzvv,nxvv,nyvv,nzvv); + + d = _Interpolate(u, v, 0, 0).real(); + dv = _Interpolate(u, v, 0, 1).real(); + dvv = _Interpolate(u, v, 0, 2).real(); + + x = pxvv + dvv * nx + dv * nxv + dv * nxv + d * nxvv; + y = pyvv + dvv * ny + dv * nyv + dv * nyv + d * nyvv; + z = pzvv + dvv * nz + dv * nzv + dv * nzv + d * nzvv; +} + +void ContinuationPatch:: +Dfdfdudv(double u, double v, double &x, double &y, double &z) +{ + double px, py, pz, nx, ny, nz, d; + double pxu, pyu, pzu, nxu, nyu, nzu, du; + double pxv, pyv, pzv, nxv, nyv, nzv, dv; + double pxuv, pyuv, pzuv, nxuv, nyuv, nzuv, duv; + + P(u,v,px,py,pz,nx,ny,nz); + Dpdu(u,v,pxu,pyu,pzu,nxu,nyu,nzu); + Dpdv(u,v,pxv,pyv,pzv,nxv,nyv,nzv); + Dpdpdudv(u,v,pxuv,pyuv,pzuv,nxuv,nyuv,nzuv); + + d = _Interpolate(u, v, 0, 0).real(); + du = _Interpolate(u, v, 1, 0).real(); + dv = _Interpolate(u, v, 1, 0).real(); + duv = _Interpolate(u, v, 1, 1).real(); + + x = pxuv + duv * nx + du * nxv + dv * nxu + d * nxuv; + y = pyuv + duv * ny + du * nyv + dv * nyu + d * nyuv; + z = pzuv + duv * nz + du * nzv + dv * nzu + d * nzuv; +} + +double ContinuationPatch::GetPou(double u, double v) +{ + return 1.; +} + diff --git a/contrib/FourierModel/ContinuationPatch.h b/contrib/FourierModel/ContinuationPatch.h new file mode 100644 index 0000000000..4e5c31f84b --- /dev/null +++ b/contrib/FourierModel/ContinuationPatch.h @@ -0,0 +1,63 @@ +#ifndef _CONTUNATION_PATCH_H_ +#define _CONTINUATION_PATCH_H_ + +#include "Patch.h" + +// The base class for the patches +class ContinuationPatch : public Patch { + private: + // third axis + double _NcrossT[3]; + // bitfield telling if we also interpolate the derivative(s) + int _derivative; + // Number of Fourier Modes + int _uModes, _vModes; + // Period Information + double _periodU, _periodV; + // Limits of Fourier Series + int _uModesLower, _uModesUpper, _vModesLower, _vModesUpper; + // data (and its first 2 derivatives) + std::complex<double> **_coeffData, **_coeffDerivU, **_coeffDerivV; + std::complex<double> **_coeffDerivUU, **_coeffDerivVV, **_coeffDerivUV; + // temporary interpolation variables + std::vector< std::complex<double> > _tmpCoeff, _tmpInterp; + // polynomial evaluator + std::complex<double> _PolyEval(std::vector< std::complex<double> > _coeff, + std::complex<double> x); + // interpolation wrapper + std::complex<double> _Interpolate(double u,double v,int uDer=0,int vDer=0); + void P(double u, double v, double &x, double &y, double &z, + double &nx, double &ny, double &nz); + bool pInverse(double x,double y,double z,double &u,double &v); + void Dpdu(double u, double v, double &x, double &y, double &z, + double &nx, double &ny, double &nz); + void Dpdv(double u, double v, double &x, double &y, double &z, + double &nx, double &ny, double &nz); + void Dpdpdudu(double u,double v,double &x,double &y,double &z, + double &nx, double &ny, double &nz); + void Dpdpdudv(double u,double v,double &x,double &y,double &z, + double &nx, double &ny, double &nz); + void Dpdpdvdv(double u,double v,double &x,double &y,double &z, + double &nx, double &ny, double &nz); + public: + ContinuationPatch(PatchInfo* PI, int derivative = 0); + virtual ~ContinuationPatch(); + + // These are the virtual functions that must be provided by all + // derived patches: GetPou() returns the original smooth + // (non-normalized) cutoff on the patch; F() and Inverse() implement + // the mapping f: (u,v)->(x,y,z) and its inverse; and the Df*() and Dn*() + // functions return the derivatives of the mapping f and unit normal n + // with respect to u and v + virtual double GetPou(double u, double v); + virtual void F(double u, double v, double &x, double &y, double &z); + virtual bool Inverse(double x,double y,double z,double &u,double &v); + virtual void Dfdu(double u, double v, double &x, double &y, double &z); + virtual void Dfdv(double u, double v, double &x, double &y, double &z); + virtual void Dfdfdudu(double u,double v,double &x,double &y,double &z); + virtual void Dfdfdudv(double u,double v,double &x,double &y,double &z); + virtual void Dfdfdvdv(double u,double v,double &x,double &y,double &z); + +}; + +#endif diff --git a/contrib/FourierModel/Curve.cpp b/contrib/FourierModel/Curve.cpp new file mode 100644 index 0000000000..81191ac27f --- /dev/null +++ b/contrib/FourierModel/Curve.cpp @@ -0,0 +1,242 @@ +#include <math.h> +#include "Message.h" +#include "Curve.h" + +Curve::Curve(IntersectionInfo* II, std::vector<Patch*> patches) : _II(II) +{ + _h = 1.e-6; + _tol = 1.e-12; + + for (int i=0;i<patches.size();i++) { + if (patches[i]->GetTag() == _II->intersectingPatches[0].patchTag) { + _patch0 = patches[i]; + break; + } + } + for (int i=0;i<patches.size();i++) + if (patches[i]->GetTag() == _II->intersectingPatches[1].patchTag) { + _patch1 = patches[i]; + break; + } + /* + int n1=64; + int n2=64; + double h1 = 1000./(n1-1); + double h2 = 1000./(n2-1); + for (int j=0;j<n1;j++) { + for (int k=0;k<n2;k++) { + double u = j*h1; + double v = k*h2; + double x, y, z; + _patch1->F(u,v,x,y,z); + printf("x(%d,%d) = %g; y(%d,%d) = %g; z(%d,%d) = %g;\n", + j+1,k+1,x,j+1,k+1,y,j+1,k+1,z); + } + } + */ + double u,v,x,y,z; + x = _II->SP[0]; y = _II->SP[1]; z = _II->SP[2]; + _patch0->Inverse(x,y,z,u,v); + _SP0[0] = u; + _SP0[1] = v; + _patch1->Inverse(x,y,z,u,v); + _SP1[0] = u; + _SP1[1] = v; + //printf("SPx = %g; SPy = %g; SPz = %g;\n",x,y,z); + + x = _II->EP[0]; y = _II->EP[1]; z = _II->EP[2]; + _patch0->Inverse(x,y,z,u,v); + _EP0[0] = u; + _EP0[1] = v; + _patch1->Inverse(x,y,z,u,v); + _EP1[0] = u; + _EP1[1] = v; + //printf("EPx = %g; EPy = %g; EPz = %g;\n",x,y,z); +} + +void Curve::F(double t, double &x, double &y, double &z) +{ + double u0, v0, u1, v1; + //Msg::Info("patch0 : %d",_patch0->GetTag()); + //Msg::Info("patch1 : %d",_patch1->GetTag()); + //Msg::Info("%g,%g,%g",_II->SP[0],_II->SP[1],_II->SP[2]); + //Msg::Info("%g,%g,%g",_II->EP[0],_II->EP[1],_II->EP[2]); + //Msg::Info("%g,%g,%g,%g",_SP0[0],_SP0[1],_EP0[0],_EP0[1]); + //Msg::Info("%g,%g,%g,%g",_SP1[0],_SP1[1],_EP1[0],_EP1[1]); + + if ((std::abs(_SP0[0]-_EP0[0])<1.e-12) && + (_patch0->_PI->periodic[0] == 1)) { + u0 = _SP0[0] + t * (1. + _EP0[0] - _SP0[0]); + if (u0 > 1.) + u0 -= floor(u0); + } + else + u0 = _SP0[0] + t * (_EP0[0] - _SP0[0]); + + if ((std::abs(_SP0[1]-_EP0[1])<1.e-12) && + (_patch0->_PI->periodic[1] == 1)) { + v0 = _SP0[1] + t * (1. + _EP0[1] - _SP0[1]); + if (u0 > 1.) + v0 -= floor(v0); + } + else + v0 = _SP0[1] + t * (_EP0[1] - _SP0[1]); + + if ((std::abs(_SP1[0]-_EP1[0])<1.e-12) && + (_patch1->_PI->periodic[0] == 1)) { + u1 = _SP1[0] + t * (1. + _EP1[0] - _SP1[0]); + if (u1 > 1.) + u1 -= floor(u1); + } + else { + u1 = _SP1[0] + t * (_EP1[0] - _SP1[0]); + } + + if ((std::abs(_SP1[1]-_EP1[1])<1.e-12) && + (_patch1->_PI->periodic[1] == 1)) { + v1 = _SP1[1] + t * (1. + _EP1[1] - _SP1[1]); + if (u1 > 1.) + v1 -= floor(v1); + } + else + v1 = _SP1[1] + t * (_EP1[1] - _SP1[1]); + + //Msg::Info("%g,%g,%g,%g",u0,v0,u1,v1); + + double x0, y0, z0; + _patch0->F(u0,v0,x0,y0,z0); + + //Msg::Info("%g,%g,%g",x0,y0,z0); + + double x1, y1, z1; + _patch1->F(u1,v1,x1,y1,z1); + + //Msg::Info("%g,%g,%g",x1,y1,z1); + + double r,u,v,rPlus,uPlus,vPlus; + + r = u0; + u = u1; + v = v1; + + double F[3]; + F[0] = x1 - x0; + F[1] = y1 - y0; + F[2] = z1 - z0; + + while ((std::abs(F[0])>_tol) || (std::abs(F[1])>_tol) || + (std::abs(F[2])>_tol)) { + rPlus = r + _h; + uPlus = u + _h; + vPlus = v + _h; + if (_patch0->_PI->periodic[0] == 1) + rPlus -= std::floor(rPlus); + if (_patch1->_PI->periodic[0] == 1) + uPlus -= std::floor(uPlus); + if (_patch1->_PI->periodic[1] == 1) + vPlus -= floor(vPlus); + //Msg::Info(" F : %g,%g,%g",F[0],F[1],F[2]); + //Msg::Info(" R : %g,%g,%g",x0,y0,z0); + double x0rPlus, y0rPlus, z0rPlus; + _patch0->F(rPlus,v0,x0rPlus,y0rPlus,z0rPlus); + double x1uPlus, y1uPlus, z1uPlus; + _patch1->F(uPlus,v,x1uPlus,y1uPlus,z1uPlus); + double x1vPlus, y1vPlus, z1vPlus; + _patch1->F(u,vPlus,x1vPlus,y1vPlus,z1vPlus); + + double Df[3][3]; + Df[0][0] = - (x0rPlus - x0) / _h; + Df[0][1] = (x1uPlus - x1) / _h; + Df[0][2] = (x1vPlus - x1) / _h; + Df[1][0] = - (y0rPlus - y0) / _h; + Df[1][1] = (y1uPlus - y1) / _h; + Df[1][2] = (y1vPlus - y1) / _h; + Df[2][0] = - (z0rPlus - z0) / _h; + Df[2][1] = (z1uPlus - z1) / _h; + Df[2][2] = (z1vPlus - z1) / _h; + + //Msg::Info("D1: %g,%g,%g",Df[0][0],Df[0][1],Df[0][2]); + //Msg::Info("D2: %g,%g,%g",Df[1][0],Df[1][1],Df[1][2]); + //Msg::Info("D3: %g,%g,%g",Df[2][0],Df[2][1],Df[2][2]); + + double det = + Df[0][0] * (Df[1][1] * Df[2][2] - Df[1][2] * Df[2][1]) + + Df[0][1] * (Df[1][2] * Df[2][0] - Df[1][0] * Df[2][2]) + + Df[0][2] * (Df[1][0] * Df[2][1] - Df[1][1] * Df[2][0]); + + //Msg::Info("det: %g",det); + + double update[3]; + update[0] = + (Df[1][1] * Df[2][2] - Df[1][2] * Df[2][1]) * F[0] + + (Df[0][2] * Df[2][1] - Df[0][1] * Df[2][2]) * F[1] + + (Df[0][1] * Df[1][2] - Df[0][2] * Df[1][1]) * F[2]; + update[1] = + (Df[1][2] * Df[2][0] - Df[1][0] * Df[2][2]) * F[0] + + (Df[0][0] * Df[2][2] - Df[0][2] * Df[2][0]) * F[1] + + (Df[0][2] * Df[1][0] - Df[0][0] * Df[1][2]) * F[2]; + update[2] = + (Df[1][0] * Df[2][1] - Df[1][1] * Df[2][0]) * F[0] + + (Df[0][1] * Df[2][0] - Df[0][0] * Df[2][1]) * F[1] + + (Df[0][0] * Df[1][1] - Df[0][1] * Df[1][0]) * F[2]; + + //Msg::Info("U: %g,%g,%g",update[0],update[1],update[2]); + + r -= update[0] / det; + u -= update[1] / det; + v -= update[2] / det; + + //Msg::Info("U/det: %g,%g,%g",update[0]/det,update[1]/det,update[2]/det); + + //Msg::Info("uv: %g,%g,%g",r,u,v); + + if (_patch0->_PI->periodic[0] == 1) + r -= std::floor(r); + if (_patch1->_PI->periodic[0] == 1) + u -= std::floor(u); + if (_patch1->_PI->periodic[1] == 1) + v -= floor(v); + + //Msg::Info("UV : %g,%g,%g",r,u,v); + + //rPlus = r + _h; + //uPlus = u + _h; + //vPlus = v + _h; + + _patch0->F(r,v0,x0,y0,z0); + _patch1->F(u,v,x1,y1,z1); + + F[0] = x1 - x0; + F[1] = y1 - y0; + F[2] = z1 - z0; + } + x = x0; y = y0; z = z0; +} + +bool Curve::Inverse(double x,double y,double z,double &t) +{ + double u0, v0; + _patch0->Inverse(x,y,z,u0,v0); + + if ((std::abs(_SP0[1]-_EP0[1])<1.e-12) && + (_patch0->_PI->periodic[1] == 1)) { + t = (v0 - _SP0[1] > 0 ? v0 - _SP0[1] : 1. + v0 - _SP0[1]); + } + else + t = (v0 - _SP0[1]) / (_EP0[1] - _SP0[1]); + + if ((t < 0.) || (t > 1.)) + return false; + else + return true; +} + +double Curve::GetPou(double t) +{ + return 1.; +} + +int Curve::GetTag() +{ + return _II->tag; +} diff --git a/contrib/FourierModel/Curve.h b/contrib/FourierModel/Curve.h new file mode 100644 index 0000000000..8606061317 --- /dev/null +++ b/contrib/FourierModel/Curve.h @@ -0,0 +1,37 @@ +#ifndef _CURVE_H_ +#define _CURVE_H_ + +#include "Patch.h" +#include "FM_Info.h" + +// The base class for the patches +class Curve { + private: + double _h, _tol; + protected: + // Patches + Patch* _patch0; + Patch* _patch1; + // End Points + double _SP0[2],_EP0[2]; + double _SP1[2],_EP1[2]; + + public: + // Intersection Information + IntersectionInfo* _II; + Curve(IntersectionInfo* II, std::vector<Patch*> patches); + virtual ~Curve() {} + + // These are the virtual functions that must be provided by all + // derived patches: GetPou() returns the original smooth + // (non-normalized) cutoff on the patch; F() and Inverse() implement + // the mapping f: (t)->(x,y,z) and its inverse; and the Df*() and Dn*() + // functions return the derivatives of the mapping f and unit normal n + // with respect to u and v + virtual double GetPou(double t); + virtual int GetTag(); + virtual void F(double t, double &x, double &y, double &z); + virtual bool Inverse(double x,double y,double z,double &t); +}; + +#endif diff --git a/contrib/FourierModel/ExactPatch.cpp b/contrib/FourierModel/ExactPatch.cpp new file mode 100644 index 0000000000..bb69ca7b76 --- /dev/null +++ b/contrib/FourierModel/ExactPatch.cpp @@ -0,0 +1,192 @@ +#include "Message.h" +#include "ExactPatch.h" + +ExactPatch::ExactPatch(PatchInfo *PI) : Patch(PI) +{ + _NcrossT[0] = _PI->normal[1] * _PI->tangent[2] - + _PI->normal[2] * _PI->tangent[1]; + _NcrossT[1] = _PI->normal[2] * _PI->tangent[0] - + _PI->normal[0] * _PI->tangent[2]; + _NcrossT[2] = _PI->normal[0] * _PI->tangent[1] - + _PI->normal[1] * _PI->tangent[0]; + + if (!strcmp(_PI->type,"plane")) { + _PI->periodic[0] = 0; + _PI->periodic[1] = 0; + } + else if (!strcmp(_PI->type,"disc")) { + _PI->periodic[0] = 0; + _PI->periodic[1] = 1; + } + else { + Msg::Info("Unknown exact patch type"); + _PI->periodic[0] = 0; + _PI->periodic[1] = 0; + } +} + +void ExactPatch::F(double u, double v, double &x, double &y, double &z) +{ + if (!strcmp(_PI->type,"plane")) { + x = _PI->origin[0] + _PI->tangent[0] * _PI->scale[0] * u + + _NcrossT[0] * _PI->scale[1] * v; + y = _PI->origin[1] + _PI->tangent[1] * _PI->scale[0] * u + + _NcrossT[1] * _PI->scale[1] * v; + z = _PI->origin[2] + _PI->tangent[2] * _PI->scale[0] * u + + _NcrossT[2] * _PI->scale[1] * v; + } + else if (!strcmp(_PI->type,"disc")) { + x = _PI->origin[0] + _PI->scale[1] * u * + (_PI->tangent[0] * cos(_PI->scale[0] * (v-0.5)) + + _NcrossT[0] * sin(_PI->scale[0] * (v-0.5))); + y = _PI->origin[1] + _PI->scale[1] * u * + (_PI->tangent[1] * cos(_PI->scale[0] * (v-0.5)) + + _NcrossT[1] * sin(_PI->scale[0] * (v-0.5))); + z = _PI->origin[2] + _PI->scale[1] * u * + (_PI->tangent[2] * cos(_PI->scale[0] * (v-0.5)) + + _NcrossT[2] * sin(_PI->scale[0] * (v-0.5))); + } + else { + Msg::Info("Unknown exact patch type"); + x = y = z = 0.; + } +} + +bool ExactPatch::Inverse(double x,double y,double z,double &u,double &v) +{ + if (!strcmp(_PI->type,"plane")) { + u = ((x - _PI->origin[0]) * _PI->tangent[0] + + (y - _PI->origin[1]) * _PI->tangent[1] + + (z - _PI->origin[2]) * _PI->tangent[2]) / _PI->scale[0]; + v = ((x - _PI->origin[0]) * _NcrossT[0] + + (y - _PI->origin[1]) * _NcrossT[1] + + (z - _PI->origin[2]) * _NcrossT[2]) / _PI->scale[1]; + } + else if (!strcmp(_PI->type,"disc")) { + double a = (x - _PI->origin[0]) * _PI->tangent[0] + + (y - _PI->origin[1]) * _PI->tangent[1] + + (z - _PI->origin[2]) * _PI->tangent[2]; + double b = (x - _PI->origin[0]) * _NcrossT[0] + + (y - _PI->origin[1]) * _NcrossT[1] + (z - _PI->origin[2]) * _NcrossT[2]; + + u = sqrt(a * a + b * b); + u /= _PI->scale[1]; + + v = atan2(b,a); + v /= _PI->scale[0]; + v += 0.5; + } + else { + Msg::Info("Unknown exat patch type"); + x = y = z = 0.; + } + return true; +} + +void ExactPatch::Dfdu(double u, double v, double &x, double &y, double &z) +{ + if (!strcmp(_PI->type,"plane")) { + x = _PI->tangent[0] * _PI->scale[0]; + y = _PI->tangent[1] * _PI->scale[0]; + z = _PI->tangent[2] * _PI->scale[0]; + } + else if (!strcmp(_PI->type,"disc")) { + x = _PI->scale[1] * (_PI->tangent[0] * cos(_PI->scale[0] * (v-0.5)) + + _NcrossT[0] * sin(_PI->scale[0] * (v-0.5))); + y = _PI->scale[1] * (_PI->tangent[1] * cos(_PI->scale[0] * (v-0.5)) + + _NcrossT[1] * sin(_PI->scale[0] * (v-0.5))); + z = _PI->scale[1] * (_PI->tangent[2] * cos(_PI->scale[0] * (v-0.5)) + + _NcrossT[2] * sin(_PI->scale[0] * (v-0.5))); + } + else { + Msg::Info("Unknown exact patch type"); + x = y = z = 0.; + } +} + +void ExactPatch::Dfdv(double u, double v, double &x, double &y, double &z) +{ + if (!strcmp(_PI->type,"plane")) { + x = _NcrossT[0] * _PI->scale[1]; + y = _NcrossT[1] * _PI->scale[1]; + z = _NcrossT[2] * _PI->scale[1]; + } + else if (!strcmp(_PI->type,"disc")) { + x = _PI->scale[1] * u * _PI->scale[0] * + (- _PI->tangent[0] * sin(_PI->scale[0] * (v-0.5)) + + _NcrossT[0] * cos(_PI->scale[0] * (v-0.5))); + y = _PI->scale[1] * u * _PI->scale[0] * + (- _PI->tangent[1] * sin(_PI->scale[0] * (v-0.5)) + + _NcrossT[1] * cos(_PI->scale[0] * (v-0.5))); + z = _PI->scale[1] * u * _PI->scale[0] * + (- _PI->tangent[2] * sin(_PI->scale[0] * (v-0.5)) + + _NcrossT[2] * cos(_PI->scale[0] * (v-0.5))); + } + else { + Msg::Info("Unknown exact patch type"); + x = y = z = 0.; + } +} + +void ExactPatch::Dfdfdudu(double u,double v,double &x,double &y,double &z) +{ + if (!strcmp(_PI->type,"plane")) { + x = y = z = 0.; + } + else if (!strcmp(_PI->type,"disc")) { + x = y = z = 0.; + } + else { + Msg::Info("Unknown exact patch type"); + x = y = z = 0.; + } +} + +void ExactPatch::Dfdfdudv(double u,double v,double &x,double &y,double &z) +{ + if (!strcmp(_PI->type,"plane")) { + x = y = z = 0.; + } + else if (!strcmp(_PI->type,"disc")) { + x = _PI->scale[1] * _PI->scale[0] * + (- _PI->tangent[0] * sin(_PI->scale[0] * (v-0.5)) + + _NcrossT[0] * cos(_PI->scale[0] * (v-0.5))); + y = _PI->scale[1] * _PI->scale[0] * + (- _PI->tangent[1] * sin(_PI->scale[0] * (v-0.5)) + + _NcrossT[1] * cos(_PI->scale[0] * (v-0.5))); + z = _PI->scale[1] * _PI->scale[0] * + (- _PI->tangent[2] * sin(_PI->scale[0] * (v-0.5)) + + _NcrossT[2] * cos(_PI->scale[0] * (v-0.5))); + } + else { + Msg::Info("Unknown exact patch type"); + x = y = z = 0.; + } +} + +void ExactPatch::Dfdfdvdv(double u,double v,double &x,double &y,double &z) +{ + if (!strcmp(_PI->type,"plane")) { + x = y = z = 0.; + } + else if (!strcmp(_PI->type,"disc")) { + x = - _PI->scale[1] * u * _PI->scale[0] * _PI->scale[0] * + (_PI->tangent[0] * cos(_PI->scale[0] * (v-0.5)) + + _NcrossT[0] * sin(_PI->scale[0] * (v-0.5))); + y = - _PI->scale[1] * u * _PI->scale[0] * _PI->scale[0] * + (- _PI->tangent[1] * cos(_PI->scale[0] * (v-0.5)) + + _NcrossT[1] * sin(_PI->scale[0] * (v-0.5))); + z = - _PI->scale[1] * u * _PI->scale[0] * _PI->scale[0] * + (- _PI->tangent[2] * cos(_PI->scale[0] * (v-0.5)) + + _NcrossT[2] * sin(_PI->scale[0] * (v-0.5))); + } + else { + Msg::Info("Unknown exact patch type"); + x = y = z = 0.; + } +} + +double ExactPatch::GetPou(double u, double v) +{ + return 1.; +} diff --git a/contrib/FourierModel/ExactPatch.h b/contrib/FourierModel/ExactPatch.h new file mode 100644 index 0000000000..dd14469414 --- /dev/null +++ b/contrib/FourierModel/ExactPatch.h @@ -0,0 +1,30 @@ +#ifndef _EXACT_PATCH_H_ +#define _EXACT_PATCH_H_ + +#include "Patch.h" + +// The base class for the patches +class ExactPatch : public Patch { + private: + // third axis + double _NcrossT[3]; + public: + ExactPatch(PatchInfo* PI); + virtual ~ExactPatch() {} + + // These are the virtual functions that must be provided by all + // derived patches: GetPou() returns the original smooth + // (non-normalized) cutoff on the patch; F() and Inverse() implement + // the mapping f: (u,v)->(x,y,z) and its inverse; and the Df*() and Dn*() + // functions return the derivatives of the mapping f and unit normal n + // with respect to u and v + virtual double GetPou(double u, double v); + virtual void F(double u, double v, double &x, double &y, double &z); + virtual bool Inverse(double x,double y,double z,double &u,double &v); + virtual void Dfdu(double u, double v, double &x, double &y, double &z); + virtual void Dfdv(double u, double v, double &x, double &y, double &z); + virtual void Dfdfdudu(double u,double v,double &x,double &y,double &z); + virtual void Dfdfdudv(double u,double v,double &x,double &y,double &z); + virtual void Dfdfdvdv(double u,double v,double &x,double &y,double &z); +}; +#endif diff --git a/contrib/FourierModel/FM_Edge.cpp b/contrib/FourierModel/FM_Edge.cpp new file mode 100644 index 0000000000..a49f7d5fad --- /dev/null +++ b/contrib/FourierModel/FM_Edge.cpp @@ -0,0 +1,123 @@ +#include "FM_Edge.h" +#include "Message.h" + +void FM_Edge::F(double t, double &x, double &y, double &z) +{ + if (_curve) { + double tStart, tEnd; + _curve->Inverse(_SP->GetX(),_SP->GetY(),_SP->GetZ(),tStart); + _curve->Inverse(_EP->GetX(),_EP->GetY(),_EP->GetZ(),tEnd); + + double tRescaled = tStart + t * (tEnd - tStart); + _curve->F(tRescaled, x, y, z); + //Msg::Info("%g %g %g",_SP->GetX(),_SP->GetY(),_SP->GetZ()); + //Msg::Info("%g %g %g",_EP->GetX(),_EP->GetY(),_EP->GetZ()); + //Msg::Info("t : %g %g %g %g",t,tRescaled, tStart, tEnd); + } + else { + x = _SP->GetX() + t * (_EP->GetX() - _SP->GetX()); + y = _SP->GetY() + t * (_EP->GetY() - _SP->GetY()); + z = _SP->GetZ() + t * (_EP->GetZ() - _SP->GetZ()); + } +} + +bool FM_Edge::Inverse(double x,double y,double z,double &t) +{ + if (_curve) { + double tStart, tEnd; + _curve->Inverse(_SP->GetX(),_SP->GetY(),_SP->GetZ(),tStart); + _curve->Inverse(_EP->GetX(),_EP->GetY(),_EP->GetZ(),tEnd); + + double tCurve; + _curve->Inverse(x, y, z, tCurve); + t = (tCurve - tStart) / (tEnd - tStart); + } + else { + if (_EP->GetX() - _SP->GetX()) + t = (x - _SP->GetX()) / (_EP->GetX() - _SP->GetX()); + else if (_EP->GetY() - _SP->GetY()) + t = (y - _SP->GetY()) / (_EP->GetY() - _SP->GetY()); + else if (_EP->GetZ() - _SP->GetZ()) + t = (z - _SP->GetZ()) / (_EP->GetZ() - _SP->GetZ()); + else { + Msg::Warning("Cannnot inver the curve"); + t = 0.; + } + } +} + +void FM_Edge::Dfdt(double t, double &x, double &y, double &z) +{ + if (_curve) { + double xMinus, yMinus, zMinus; + double xPlus, yPlus, zPlus; + + double tStart, tEnd; + _curve->Inverse(_SP->GetX(),_SP->GetY(),_SP->GetZ(),tStart); + _curve->Inverse(_EP->GetX(),_EP->GetY(),_EP->GetZ(),tEnd); + + double h = 1.e-10; + double tRescaled = tStart + t * (tEnd - tStart); + if (t+0.5*h > 1.) { + _curve->F(tRescaled, xPlus, yPlus, zPlus); + double tMinus = tStart + (t - h) * (tEnd - tStart); + _curve->F(tMinus, xMinus, yMinus, zMinus); + } + else if (t-0.5*h < 0.) { + _curve->F(tRescaled, xMinus, yMinus, zMinus); + double tPlus = tStart + (t + h) * (tEnd - tStart); + _curve->F(tPlus, xPlus, yPlus, zPlus); + } + else { + double tPlus = tStart + (t + 0.5 * h) * (tEnd - tStart); + double tMinus = tStart + (t - 0.5 * h) * (tEnd - tStart); + _curve->F(tPlus, xPlus, yPlus, zPlus); + _curve->F(tMinus, xMinus, yMinus, zMinus); + } + x = (xPlus - xMinus) / h; + y = (yPlus - yMinus) / h; + z = (zPlus - zMinus) / h; + } + else { + x = _EP->GetX() - _SP->GetX(); + y = _EP->GetY() - _SP->GetY(); + z = _EP->GetZ() - _SP->GetZ(); + } +} + +void FM_Edge::Dfdfdtdt(double t, double &x, double &y, double &z) +{ + if (_curve) { + double xMinus, yMinus, zMinus; + double xPlus, yPlus, zPlus; + + double tStart, tEnd; + _curve->Inverse(_SP->GetX(),_SP->GetY(),_SP->GetZ(),tStart); + _curve->Inverse(_EP->GetX(),_EP->GetY(),_EP->GetZ(),tEnd); + + double h = 1.e-10; + double tRescaled = tStart + t * (tEnd - tStart); + if (t+0.5*h > 1.) { + Dfdt(tRescaled, xPlus, yPlus, zPlus); + double tMinus = tStart + (t - h) * (tEnd - tStart); + Dfdt(tMinus, xMinus, yMinus, zMinus); + } + else if (t-0.5*h < 0.) { + Dfdt(tRescaled, xMinus, yMinus, zMinus); + double tPlus = tStart + (t + h) * (tEnd - tStart); + Dfdt(tPlus, xPlus, yPlus, zPlus); + } + else { + double tPlus = tStart + (t + 0.5 * h) * (tEnd - tStart); + double tMinus = tStart + (t - 0.5 * h) * (tEnd - tStart); + Dfdt(tPlus, xPlus, yPlus, zPlus); + Dfdt(tMinus, xMinus, yMinus, zMinus); + } + x = (xPlus - xMinus) / h; + y = (yPlus - yMinus) / h; + z = (zPlus - zMinus) / h; + } + else { + x = y = z = 0.; + } +} diff --git a/contrib/FourierModel/FM_Edge.h b/contrib/FourierModel/FM_Edge.h new file mode 100644 index 0000000000..c80c7b872a --- /dev/null +++ b/contrib/FourierModel/FM_Edge.h @@ -0,0 +1,37 @@ +#ifndef _FM_EDGE_H_ +#define _FM_EDGE_H_ + +#include "Curve.h" +#include "FM_Vertex.h" + +class FM_Edge { + private: + 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) {} + virtual ~FM_Edge() {} + + inline FM_Vertex* GetStartPoint() { return _SP; } + inline FM_Vertex* GetEndPoint() { return _EP; } + + inline void SetStartPoint(FM_Vertex* SP) { _SP = SP; } + inline void SetStartPoint(double x, double y, double z) { + _SP = new FM_Vertex(x,y,z); + } + inline void SetEndPoint(FM_Vertex* EP) { _EP = EP; } + inline void SetEndPoint(double x, double y, double z) { + _EP = new FM_Vertex(x,y,z); + } + + void F(double t, double &x, double &y, double &z); + bool Inverse(double x,double y,double z,double &t); + void Dfdt(double t, double &x, double &y, double &z); + void Dfdfdtdt(double t, double &x, double &y, double &z); +}; + +#endif diff --git a/contrib/FourierModel/FM_Face.cpp b/contrib/FourierModel/FM_Face.cpp new file mode 100644 index 0000000000..a25f26ee02 --- /dev/null +++ b/contrib/FourierModel/FM_Face.cpp @@ -0,0 +1,147 @@ +#include "FM_Face.h" +#include "Message.h" + +void FM_Face::F(double u, double v, double &x, double &y, double &z) { + if (_edge.size() == 0) { + _patch->F(u,v,x,y,z); + } + else if (_edge.size() == 1) { + // sanity check + double cx, cy, cz; + _patch->F(0.,0.,cx,cy,cz); + double px, py, pz; + _edge[0]->F(v,px,py,pz); + double R = sqrt((px-cx)*(px-cx)+(py-cy)*(py-cy)+(pz-cz)*(pz-cz)); + _patch->F(u*R,v,x,y,z); + } + else if (_edge.size() == 4) { + double xD, yD, zD, uD, vD; + double xU, yU, zU, uU, vU; + _edge[0]->F(v,xD,yD,zD); + _patch->Inverse(xD,yD,zD,uD,vD); + _edge[2]->F(v,xU,yU,zU); + _patch->Inverse(xU,yU,zU,uU,vU); + + double U = uD + u * (uU - uD); + double V = vD; + + _patch->F(U,V,x,y,z); + } + else { + Msg::Info("Such a face not implemented yet"); + x = y = z = 0.; + } +} + +bool FM_Face::Inverse(double x,double y,double z,double &u, double &v) +{ + if (_edge.size() == 0) { + _patch->Inverse(x,y,z,u,v); + } + else if (_edge.size() == 1) { + double n[3], t[3], s[3], c[3], r[3]; + _patch->F(0.,0.,c[0],c[1],c[2]); + for (int i=0;i<3;i++) { + t[i] = _patch->_PI->tangent[i]; + n[i] = _patch->_PI->normal[i]; + } + + s[0] = n[1] * t[2] - n[2] * t[1]; + s[1] = n[2] * t[0] - n[0] * t[2]; + s[2] = n[0] * t[1] - n[1] * t[0]; + + r[0] = x - c[0]; + r[1] = y - c[1]; + r[2] = z - c[2]; + + double norm = sqrt(r[0]*r[0]+r[1]*r[1]+r[2]*r[2]); + for (int i=0;i<3;i++) + r[i] /= norm; + double xx, yy; + for (int i=0;i<3;i++) { + xx += r[i] * t[i]; + yy += r[i] * s[i]; + } + v = atan2(yy, xx)/(2. * M_PI) +0.5; + double px, py, pz; + _edge[0]->F(v,px,py,pz); + double R = sqrt((px-c[0])*(px-c[0])+(py-c[1])*(py-c[1])+ + (pz-c[2])*(pz-c[2])); + u = norm / R; + } + else if (_edge.size() == 4) { + double U, V; + _patch->Inverse(x,y,z,U,V); + double u0,v0,u1,v1; + double xD, yD, zD, uD, vD; + double xU, yU, zU, uU, vU; + _edge[0]->F(0,xD,yD,zD); + _patch->Inverse(xD,yD,zD,u0,v0); + _edge[0]->F(1,xD,yD,zD); + _patch->Inverse(xD,yD,zD,u1,v1); + v = (V-v0)/(v1-v0); + _edge[0]->F(v,xD,yD,zD); + _patch->Inverse(xD,yD,zD,uD,vD); + _edge[2]->F(v,xU,yU,zU); + _patch->Inverse(xU,yU,zU,uU,vU); + + u = (U - uD) / (uU - uD); + } + else { + Msg::Info("Such a face not implemented yet"); + u = v = 0.; + } + +} + +void FM_Face::Dfdu(double u, double v, double &x, double &y, double &z) +{ + Msg::Info("Not implemented yet."); + x = y = z = 0.; +} + +void FM_Face::Dfdv(double u, double v, double &x, double &y, double &z) +{ + Msg::Info("Not implemented yet."); + x = y = z = 0.; +} + +void FM_Face::Dfdfdudu(double u, double v, double &x, double &y, double &z) +{ + Msg::Info("Not implemented yet."); + x = y = z = 0.; +} + +void FM_Face::Dfdfdudv(double u, double v, double &x, double &y, double &z) +{ + Msg::Info("Not implemented yet."); + x = y = z = 0.; +} + +void FM_Face::Dfdfdvdv(double u, double v, double &x, double &y, double &z) +{ + Msg::Info("Not implemented yet."); + x = y = z = 0.; +} + +void FM_Face::GetNormal(double u, double v, double &x, double &y, double &z) +{ + double dfdu[3], dfdv[3]; + Dfdu(u, v, dfdu[0], dfdu[1], dfdu[2]); + Dfdv(u, v, dfdv[0], dfdv[1], dfdv[2]); + x = dfdu[1] * dfdv[2] - dfdu[2] * dfdv[1]; + y = dfdu[2] * dfdv[0] - dfdu[0] * dfdv[2]; + z = dfdu[0] * dfdv[1] - dfdu[1] * dfdv[0]; +} + +void FM_Face:: +GetUnitNormal(double u, double v, double &x, double &y, double &z) +{ + GetNormal(u, v, x, y, z); + double norm = sqrt(x * x + y * y + z * z); + if(norm > 0.) { + x /= norm; + y /= norm; + z /= norm; + } +} diff --git a/contrib/FourierModel/FM_Face.h b/contrib/FourierModel/FM_Face.h new file mode 100644 index 0000000000..f8f7a6e0c1 --- /dev/null +++ b/contrib/FourierModel/FM_Face.h @@ -0,0 +1,33 @@ +#ifndef _FM_FACE_H_ +#define _FM_FACE_H_ + +#include "Patch.h" +#include "FM_Edge.h" + +class FM_Face { + private: + Patch* _patch; + std::vector<FM_Edge*> _edge; + public: + FM_Face() : _patch(0) {} + FM_Face(Patch* patch) : _patch(patch) {} + FM_Face(Patch* patch, std::vector<FM_Edge*> edge) : + _patch(patch), _edge(edge) {} + virtual ~FM_Face() {} + + 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]; } + + void F(double u, double v, double &x, double &y, double &z); + bool Inverse(double x,double y,double z,double &u, double &v); + void Dfdu(double u, double v, double &x, double &y, double &z); + void Dfdv(double u, double v, double &x, double &y, double &z); + void Dfdfdudu(double u, double v, double &x, double &y, double &z); + void Dfdfdudv(double u, double v, double &x, double &y, double &z); + void Dfdfdvdv(double u, double v, double &x, double &y, double &z); + void GetUnitNormal(double u,double v,double &x,double &y,double &z); + void GetNormal(double u, double v, double &x, double &y, double &z); +}; + +#endif diff --git a/contrib/FourierModel/FM_Info.cpp b/contrib/FourierModel/FM_Info.cpp new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/contrib/FourierModel/FM_Info.cpp @@ -0,0 +1 @@ + diff --git a/contrib/FourierModel/FM_Info.h b/contrib/FourierModel/FM_Info.h new file mode 100644 index 0000000000..4eb3a0071f --- /dev/null +++ b/contrib/FourierModel/FM_Info.h @@ -0,0 +1,37 @@ +#ifndef _FM_INFO_H_ +#define _FM_INFO_H_ + +#include <complex> +#include <vector> + +class PatchInfo { + public: + char type[16]; + char projection[16]; + int tag; + int nModes[2]; + int periodic[2]; + double normal[3]; + double origin[3]; + double tangent[3]; + double scale[2]; + std::vector<std::vector<std::complex<double> > > coeff; + + PatchInfo() {} + virtual ~PatchInfo() {} +}; + +class IntersectionInfo { + public: + int tag; + double SP[3]; + double EP[3]; + struct { + int patchTag; + } intersectingPatches[2]; + + IntersectionInfo() {} + virtual ~IntersectionInfo() {} +}; + +#endif diff --git a/contrib/FourierModel/FM_Reader.cpp b/contrib/FourierModel/FM_Reader.cpp new file mode 100644 index 0000000000..37cfa6c072 --- /dev/null +++ b/contrib/FourierModel/FM_Reader.cpp @@ -0,0 +1,108 @@ +#include <iostream> +#include <fstream> +#include "Message.h" +#include "FM_Reader.h" + +FM_Reader::FM_Reader(const char* fn) +{ + char c; + char continuation[16] = "continuation"; + std::ifstream InputFile(fn); + if (!InputFile) { + Msg::Info("Failed to open input file."); + exit(EXIT_FAILURE); + } + InputFile >> _nPatches; + InputFile >> _nIntersections; + + for (int i=0;i<_nPatches;i++) { + _patchList.push_back(new PatchInfo);; + InputFile >> _patchList[i]->tag; + InputFile >> _patchList[i]->type; + InputFile >> _patchList[i]->projection; + InputFile >> _patchList[i]->normal[0] >> _patchList[i]->normal[1] >> + _patchList[i]->normal[2]; + InputFile >> _patchList[i]->origin[0] >> _patchList[i]->origin[1] >> + _patchList[i]->origin[2]; + InputFile >> _patchList[i]->tangent[0] >> _patchList[i]->tangent[1] >> + _patchList[i]->tangent[2]; + InputFile >> _patchList[i]->scale[0] >> _patchList[i]->scale[1]; + if (!strcmp(_patchList[i]->type,continuation)) { + InputFile >> _patchList[i]->periodic[0] >> _patchList[i]->periodic[1]; + InputFile >> _patchList[i]->nModes[0] >> _patchList[i]->nModes[1]; + _patchList[i]->coeff.resize(_patchList[i]->nModes[0]); + for (int j=0;j<_patchList[i]->nModes[0];j++) { + _patchList[i]->coeff[j].resize(_patchList[i]->nModes[1]); + for (int k=0;k<_patchList[i]->nModes[1];k++) { + double realCoeff, imagCoeff; + InputFile >> realCoeff >> imagCoeff; + _patchList[i]->coeff[j][k] = + std::complex<double>(realCoeff,imagCoeff); + } + } + } + } + for (int i=0;i<_nIntersections;i++) { + _intersectionList.push_back(new IntersectionInfo); + InputFile >> _intersectionList[i]->tag; + InputFile >> _intersectionList[i]->SP[0] >> _intersectionList[i]->SP[1] + >> _intersectionList[i]->SP[2]; + InputFile >> _intersectionList[i]->EP[0] >> _intersectionList[i]->EP[1] + >> _intersectionList[i]->EP[2]; + InputFile >> _intersectionList[i]->intersectingPatches[0].patchTag; + InputFile >> _intersectionList[i]->intersectingPatches[1].patchTag; + } + + _patch.resize(_nPatches); + _intersection.resize(_nIntersections); + + for (int i=0;i<_nPatches;i++) { + PatchInfo* PI = _patchList[i]; + if (!strcmp(PI->type,continuation)) + _patch[PI->tag] = new ContinuationPatch(PI,2); + else + _patch[PI->tag] = new ExactPatch(PI); + } + for (int i=0;i<_nIntersections;i++) { + IntersectionInfo* II = _intersectionList[i]; + _intersection[II->tag] = new Curve(II,_patch); + } + + InputFile >> _nFaces; + for (int i=0;i<_nFaces;i++) { + int faceTag, nEdges; + InputFile >> faceTag; + _face.push_back(new FM_Face(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))); + } + } +} + +Patch* FM_Reader::GetPatch(int tag) +{ + for (int i=0;i<_patch.size();i++) + if (_patch[i]->GetTag() == tag) + return _patch[i]; +} + +Curve* FM_Reader::GetIntersection(int tag) +{ + for (int i=0;i<_intersection.size();i++) + if (_intersection[i]->GetTag() == tag) + return _intersection[i]; +} diff --git a/contrib/FourierModel/FM_Reader.h b/contrib/FourierModel/FM_Reader.h new file mode 100644 index 0000000000..98940271bf --- /dev/null +++ b/contrib/FourierModel/FM_Reader.h @@ -0,0 +1,38 @@ +#ifndef _FM_READER_H_ +#define _FM_READER_H_ + +#include <vector> +#include <complex> +#include "Curve.h" +#include "ExactPatch.h" +#include "ContinuationPatch.h" +#include "FM_Info.h" +#include "FM_Face.h" + +class FM_Reader { + private: + int _nFaces; + int _nPatches; + int _nIntersections; + std::vector<PatchInfo*> _patchList; + std::vector<IntersectionInfo*> _intersectionList; + std::vector<FM_Face*> _face; + std::vector<Patch*> _patch; + std::vector<Curve*> _intersection; + public: + FM_Reader(const char* fn); + virtual ~FM_Reader() {} + + 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_Face* GetFace(int i) { return _face[i]; } + + Patch* GetPatch(int tag); + Curve* GetIntersection(int tag); +}; + +#endif diff --git a/contrib/FourierModel/FM_Vertex.cpp b/contrib/FourierModel/FM_Vertex.cpp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/contrib/FourierModel/FM_Vertex.cpp @@ -0,0 +1,2 @@ + + diff --git a/contrib/FourierModel/FM_Vertex.h b/contrib/FourierModel/FM_Vertex.h new file mode 100644 index 0000000000..2bc0fe0cae --- /dev/null +++ b/contrib/FourierModel/FM_Vertex.h @@ -0,0 +1,21 @@ +#ifndef _FM_VERTEX_H_ +#define _FM_VERTEX_H_ + +class FM_Vertex { + private: + 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) {} + virtual ~FM_Vertex() {} + + inline double GetX() { return _x; } + inline double GetY() { return _y; } + inline double GetZ() { return _z; } + + inline void SetX(double x) { _x = x; } + inline void SetY(double y) { _y = y; } + inline void SetZ(double z) { _z = z; } +}; + +#endif diff --git a/contrib/FourierModel/Main.cpp b/contrib/FourierModel/Main.cpp new file mode 100644 index 0000000000..1dc9e6185a --- /dev/null +++ b/contrib/FourierModel/Main.cpp @@ -0,0 +1,117 @@ +#include <cstring> +#include <iostream> +#include "Utils.h" +#include "Message.h" +#include "FM_Reader.h" + +int main(int argc, char *argv[]) +{ + char* fn; + char continuation[16] = "continuation"; + + if (argc == 1) { + Msg::Info("Reading from default file : untitled.fm"); + fn = "untitled.fm"; + } + else + fn = argv[1]; + + FM_Reader reader(fn); + + /* + + int n1=64; + int n2=64; + double h1 = 1./(n1-1); + double h2 = 1./(n2-1); + for (int j=0;j<n1;j++) { + for (int k=0;k<n2;k++) { + double u = j*h1; + double v = k*h2; + double x, y, z; + patches[0]->F(u,v,x,y,z); + printf("x(%d,%d) = %g; y(%d,%d) = %g; z(%d,%d) = %g;\n", + j+1,k+1,x,j+1,k+1,y,j+1,k+1,z); + } + } + + for (int i=0;i<reader.GetNumIntersections();i++) { + int n=128; + double h = 1./(n-1); + for (int j=0;j<n;j++) { + double t = j*h; + double x, y, z; + reader.GetIntersection(i)->F(t,x,y,z); + printf("x(%d,%d) = %g; y(%d,%d) = %g; z(%d,%d) = %g;\n", + i+1,j+1,x,i+1,j+1,y,i+1,j+1,z); + } + } + + for (int i=0;i<reader.GetNumPatches();i++) { + std::cout << reader.GetPatchList()[i]->tag << "\n"; + std::cout << reader.GetPatchList()[i]->type << "\n"; + std::cout << reader.GetPatchList()[i]->projection << "\n"; + std::cout << reader.GetPatchList()[i]->normal[0] << " " << + reader.GetPatchList()[i]->normal[1] << " " << + reader.GetPatchList()[i]->normal[2] << "\n"; + std::cout << reader.GetPatchList()[i]->origin[0] << " " << + reader.GetPatchList()[i]->origin[1] << " " << + reader.GetPatchList()[i]->origin[2] << "\n"; + std::cout << reader.GetPatchList()[i]->tangent[0] << " " << + reader.GetPatchList()[i]->tangent[1] << " " << + reader.GetPatchList()[i]->tangent[2] << "\n"; + if (!strcmp(reader.GetPatchList()[i]->type,continuation)) { + std::cout << reader.GetPatchList()[i]->periodic[0] << " " << + reader.GetPatchList()[i]->periodic[1] << "\n"; + std::cout << reader.GetPatchList()[i]->nModes[0] << " " << + reader.GetPatchList()[i]->nModes[1] << "\n"; + for (int j=0;j<reader.GetPatchList()[i]->nModes[0];j++) + for (int k=0;k<reader.GetPatchList()[i]->nModes[1];k++) + std::cout << reader.GetPatchList()[i]->coeff[j][k].real() << " " << + reader.GetPatchList()[i]->coeff[j][k].imag() << "\n"; + } + } + + for (int i=0;i<reader.GetIntersectionList().size();i++) { + std::cout << reader.GetIntersectionList()[i]->tag << "\n"; + std::cout << reader.GetIntersectionList()[i]->SP[0] << + " " << reader.GetIntersectionList()[i]->SP[1] << " " << + reader.GetIntersectionList()[i]->SP[2] << "\n"; + std::cout << reader.GetIntersectionList()[i]->EP[0] << + " " << reader.GetIntersectionList()[i]->EP[1] << " " << + reader.GetIntersectionList()[i]->EP[2] << "\n"; + std::cout << reader.GetIntersectionList()[i]-> + intersectingPatches[0].patchTag << "\n"; + std::cout << reader.GetIntersectionList()[i]-> + intersectingPatches[1].patchTag << "\n"; + } + */ + + int nU=64; + int nV=64; + + std::vector<int> color(3); + color[0] = 0; color[1] = 0; color[2] = 1; + + std::vector<std::vector<double> > x(nU,std::vector<double>(nV)); + std::vector<std::vector<double> > y(nU,std::vector<double>(nV)); + std::vector<std::vector<double> > z(nU,std::vector<double>(nV)); + + std::vector<std::vector<int> > mask = ones(nU,nV); + + for (int i=0;i<reader.GetNumFaces();i++) { + double hU = 1./(nU-1); + double hV = 1./(nV-1); + for (int j=0;j<nU;j++) { + for (int k=0;k<nV;k++) { + double u = j*hU; + double v = k*hV; + reader.GetFace(i)->F(u,v,x[j][k],y[j][k],z[j][k]); + } + } + if (i == 0) + plotSceneViewer(0,"snc.iv",color,x,y,z,nU,nV,mask); + else + plotSceneViewer(1,"snc.iv",color,x,y,z,nU,nV,mask); + } +} diff --git a/contrib/FourierModel/Makefile b/contrib/FourierModel/Makefile new file mode 100644 index 0000000000..5e33ac5b8c --- /dev/null +++ b/contrib/FourierModel/Makefile @@ -0,0 +1,55 @@ +include ../../variables + +LIB = ../../lib/libGmshFourierModel.a + +CFLAGS = ${OPTIM} ${FLAGS} + +SRC = ContinuationPatch.cpp\ + ExactPatch.cpp\ + Patch.cpp\ + Curve.cpp\ + FM_Edge.cpp\ + FM_Face.cpp\ + FM_Info.cpp\ + FM_Reader.cpp\ + FM_Vertex.cpp\ + Message.cpp + +OBJ = ${SRC:.cpp=.o} + +.SUFFIXES: .o .cpp + +${LIB}: ${OBJ} + ${AR} ${LIB} ${OBJ} + ${RANLIB} ${LIB} + +.cpp.o: + ${CXX} ${CFLAGS} -c $< + +clean: + rm -f *.o + +depend: + (sed '/^# DO NOT DELETE THIS LINE/q' Makefile && \ + ${CXX} -MM ${CFLAGS} ${SRC} \ + ) >Makefile.new + cp Makefile Makefile.bak + cp Makefile.new Makefile + rm -f Makefile.new + +# DO NOT DELETE THIS LINE +ContinuationPatch.o: ContinuationPatch.cpp Message.h ContinuationPatch.h \ + Patch.h FM_Info.h +ExactPatch.o: ExactPatch.cpp Message.h ExactPatch.h Patch.h FM_Info.h +Patch.o: Patch.cpp Patch.h FM_Info.h +Curve.o: Curve.cpp Message.h Curve.h Patch.h FM_Info.h +FM_Edge.o: FM_Edge.cpp FM_Edge.h Curve.h Patch.h FM_Info.h FM_Vertex.h \ + Message.h +FM_Face.o: FM_Face.cpp FM_Face.h Patch.h FM_Info.h FM_Edge.h Curve.h \ + FM_Vertex.h Message.h +FM_Info.o: FM_Info.cpp +FM_Reader.o: FM_Reader.cpp Message.h FM_Reader.h Curve.h Patch.h \ + FM_Info.h ExactPatch.h ContinuationPatch.h FM_Face.h FM_Edge.h \ + FM_Vertex.h +FM_Vertex.o: FM_Vertex.cpp +Message.o: Message.cpp Message.h diff --git a/contrib/FourierModel/Message.cpp b/contrib/FourierModel/Message.cpp new file mode 100644 index 0000000000..2034750c02 --- /dev/null +++ b/contrib/FourierModel/Message.cpp @@ -0,0 +1,156 @@ +#include <stdlib.h> +#include <stdio.h> +#include <sys/time.h> +#include <sys/resource.h> + +#if defined(__APPLE__) +#define RUSAGE_SELF 0 +#define RUSAGE_CHILDREN -1 +#endif + +#include "Message.h" + +int Message::_commRank = 0; +int Message::_commSize = 1; +int Message::_verbosity = 3; +int Message::_progressMeterStep = 10; +int Message::_progressMeterCurrent = 0; + +void Message::Fatal(char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + if(_commSize > 1) + fprintf(stderr, "Fatal : [On processor %d] ", _commRank); + else + fprintf(stderr, "Fatal : "); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); + exit(1); +} + +void Message::Error(char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + if(_commSize > 1) + fprintf(stderr, "Error : [On processor %d] ", _commRank); + else + fprintf(stderr, "Error : "); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); +} + +void Message::Warning(char *fmt, ...) +{ + if(_commRank) return; + if(_verbosity >= 1){ + va_list args; + va_start(args, fmt); + fprintf(stderr, "Warning : "); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); + } +} + +void Message::Info(char *fmt, ...) +{ + if(_commRank) return; + if(_verbosity >= 2){ + va_list args; + va_start(args, fmt); + fprintf(stderr, "Info : "); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); + } +} + +void Message::Debug(char *fmt, ...) +{ + if(_commRank) return; + if(_verbosity >= 99){ + va_list args; + va_start(args, fmt); + fprintf(stderr, "Debug : "); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); + } +} + +void Message::Cpu(char *fmt, ...) +{ + if(_commRank) return; + if(_verbosity >= 1){ + static struct rusage r; + getrusage(RUSAGE_SELF, &r); + double s = (double)r.ru_utime.tv_sec; + double us = (double)r.ru_utime.tv_usec; + double mem = (double)r.ru_maxrss; + va_list args; + va_start(args, fmt); + fprintf(stderr, "Info : "); + vfprintf(stderr, fmt, args); + if(mem) + fprintf(stderr, " (CPU = %gs Mem = %gkb)\n", s + 1.e-6 * us, mem); + else + fprintf(stderr, " (CPU = %gs)\n", s + 1.e-6 * us); + va_end(args); + } +} + +void Message::ResetProgressMeter(int step) +{ + _progressMeterStep = step; + _progressMeterCurrent = 0; +} + +void Message::ProgressMeter(int n, int N, char *fmt, ...) +{ + if(_commRank) return; + if(_verbosity >= 2){ + va_list args; + va_start(args, fmt); + if(100. * (double)n/(double)N >= _progressMeterCurrent){ + vfprintf(stderr, fmt, args); + fprintf(stderr, "(%d %%) \r", _progressMeterCurrent); + _progressMeterCurrent += _progressMeterStep; + } + if(n >= N - 1) + fprintf(stderr, "Done! \r"); + } +} + +void Message::ProgressMeter(int n, int N) +{ + if(_commRank) return; + if(_verbosity >= 2){ + if(100. * (double)n/(double)N >= _progressMeterCurrent){ + fprintf(stderr, "(%d %%)\r", _progressMeterCurrent); + _progressMeterCurrent += _progressMeterStep; + } + if(n >= N - 1) + fprintf(stderr, " \r") ; + } +} + +#if defined(HAVE_PETSC) + +#include "petsc.h" + +void Message::Barrier() +{ + MPI_Barrier(PETSC_COMM_WORLD); +} + +#else + +void Message::Barrier() +{ +} + +#endif diff --git a/contrib/FourierModel/Message.h b/contrib/FourierModel/Message.h new file mode 100644 index 0000000000..f5b9a65464 --- /dev/null +++ b/contrib/FourierModel/Message.h @@ -0,0 +1,36 @@ +#ifndef _MESSAGE_H_ +#define _MESSAGE_H_ + +#include <stdarg.h> + +// a class to manage messages +class Message { + private: + // current cpu number and total number of cpus + static int _commRank, _commSize; + // verbosity level + static int _verbosity; + // step (in %) of the progress meter and current progress % + static int _progressMeterStep, _progressMeterCurrent; + public: + Message() {} + static int GetCommRank(){ return _commRank; } + static int GetCommSize(){ return _commSize; } + static void SetCommRank(int val){ _commRank = val; } + static void SetCommSize(int val){ _commSize = val; } + static void Barrier(); + static void SetVerbosity(int val){ _verbosity = val; } + static void Fatal(char *fmt, ...); + static void Error(char *fmt, ...); + static void Warning(char *fmt, ...); + static void Info(char *fmt, ...); + static void Debug(char *fmt, ...); + static void Cpu(char *fmt, ...); + static void ProgressMeter(int n, int N); + static void ProgressMeter(int n, int N, char *fmt, ...); + static void ResetProgressMeter(int step=10); +}; + +typedef Message Msg; + +#endif diff --git a/contrib/FourierModel/Patch.cpp b/contrib/FourierModel/Patch.cpp new file mode 100644 index 0000000000..c8bf1ec899 --- /dev/null +++ b/contrib/FourierModel/Patch.cpp @@ -0,0 +1,84 @@ +#include <cmath> +#include "Patch.h" + +void Patch::GetNormal(double u, double v, double &x, double &y, double &z) +{ + double dfdu[3], dfdv[3]; + Dfdu(u, v, dfdu[0], dfdu[1], dfdu[2]); + Dfdv(u, v, dfdv[0], dfdv[1], dfdv[2]); + x = dfdu[1] * dfdv[2] - dfdu[2] * dfdv[1]; + y = dfdu[2] * dfdv[0] - dfdu[0] * dfdv[2]; + z = dfdu[0] * dfdv[1] - dfdu[1] * dfdv[0]; +} + +void Patch::GetUnitNormal(double u, double v, double &x, double &y, double &z) +{ + GetNormal(u, v, x, y, z); + double norm = sqrt(x * x + y * y + z * z); + if(norm > 0.) { + x /= norm; + y /= norm; + z /= norm; + } +} + +void Patch::Dndu(double u, double v, double &x, double &y, double &z) +{ + double n[3],dfdu[3],dfdv[3],dfdfdudu[3],dfdfdudv[3],dfdfdvdv[3],dndu[3]; + Dfdu(u, v, dfdu[0], dfdu[1], dfdu[2]); + Dfdv(u, v, dfdv[0], dfdv[1], dfdv[2]); + Dfdfdudu(u, v, dfdfdudu[0], dfdfdudu[1], dfdfdudu[2]); + Dfdfdudv(u, v, dfdfdudv[0], dfdfdudv[1], dfdfdudv[2]); + Dfdfdvdv(u, v, dfdfdvdv[0], dfdfdvdv[1], dfdfdvdv[2]); + GetNormal(u,v,n[0],n[1],n[2]); + double norm = sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]); + double normSquared = norm * norm; + double normCubed = normSquared * norm; + + dndu[0] = dfdfdudu[1] * dfdv[2] + dfdu[1] * dfdfdudv[2] - + dfdfdudu[2] * dfdv[1] - dfdu[2] * dfdfdudv[1]; + dndu[1] = dfdfdudu[2] * dfdv[0] + dfdu[2] * dfdfdudv[0] - + dfdfdudu[0] * dfdv[2] - dfdu[0] * dfdfdudv[2]; + dndu[2] = dfdfdudu[0] * dfdv[1] + dfdu[0] * dfdfdudv[1] - + dfdfdudu[1] * dfdv[0] - dfdu[1] * dfdfdudv[0]; + + x = ((normSquared - n[0]*n[0])*dndu[0] - n[0]*n[1]*dndu[1] - + n[0]*n[2]*dndu[2]) / normCubed; + y = ((normSquared - n[1]*n[1])*dndu[1] - n[1]*n[0]*dndu[0] - + n[1]*n[2]*dndu[2]) / normCubed; + z = ((normSquared - n[2]*n[2])*dndu[2] - n[2]*n[0]*dndu[0] - + n[2]*n[1]*dndu[1]) / normCubed; +} + +void Patch::Dndv(double u, double v, double &x, double &y, double &z) +{ + double n[3],dfdu[3],dfdv[3],dfdfdudu[3],dfdfdudv[3],dfdfdvdv[3],dndv[3]; + Dfdu(u, v, dfdu[0], dfdu[1], dfdu[2]); + Dfdv(u, v, dfdv[0], dfdv[1], dfdv[2]); + Dfdfdudu(u, v, dfdfdudu[0], dfdfdudu[1], dfdfdudu[2]); + Dfdfdudv(u, v, dfdfdudv[0], dfdfdudv[1], dfdfdudv[2]); + Dfdfdvdv(u, v, dfdfdvdv[0], dfdfdvdv[1], dfdfdvdv[2]); + GetNormal(u,v,n[0],n[1],n[2]); + double norm = sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]); + double normSquared = norm * norm; + double normCubed = normSquared * norm; + + dndv[0] = dfdfdudv[1] * dfdv[2] + dfdu[1] * dfdfdvdv[2] - + dfdfdudv[2] * dfdv[1] - dfdu[2] * dfdfdvdv[1]; + dndv[1] = dfdfdudv[2] * dfdv[0] + dfdu[2] * dfdfdvdv[0] - + dfdfdudv[0] * dfdv[2] - dfdu[0] * dfdfdvdv[2]; + dndv[2] = dfdfdudv[0] * dfdv[1] + dfdu[0] * dfdfdvdv[1] - + dfdfdudv[1] * dfdv[0] - dfdu[1] * dfdfdvdv[0]; + + x = ((normSquared - n[0]*n[0])*dndv[0] - n[0]*n[1]*dndv[1] - + n[0]*n[2]*dndv[2]) / normCubed; + y = ((normSquared - n[1]*n[1])*dndv[1] - n[1]*n[0]*dndv[0] - + n[1]*n[2]*dndv[2]) / normCubed; + z = ((normSquared - n[2]*n[2])*dndv[2] - n[2]*n[0]*dndv[0] - + n[2]*n[1]*dndv[1]) / normCubed; +} + +int Patch::GetTag() +{ + return _PI->tag; +} diff --git a/contrib/FourierModel/Patch.h b/contrib/FourierModel/Patch.h new file mode 100644 index 0000000000..60d78a46b0 --- /dev/null +++ b/contrib/FourierModel/Patch.h @@ -0,0 +1,40 @@ +#ifndef _PATCH_H_ +#define _PATCH_H_ + +#include "FM_Info.h" + +// The base class for the patches +class Patch { + public: + PatchInfo* _PI; + Patch() :_PI(0) {} + Patch(PatchInfo* PI) : _PI(PI) {} + virtual ~Patch() {} + + int GetTag(); + + // These are the virtual functions that must be provided by all + // derived patches: GetPou() returns the original smooth + // (non-normalized) cutoff on the patch; F() and Inverse() implement + // the mapping f: (u,v)->(x,y,z) and its inverse; and the Df*() and Dn*() + // functions return the derivatives of the mapping f and unit normal n + // with respect to u and v + virtual double GetPou(double u, double v) = 0; + virtual void F(double u, double v, double &x, double &y, double &z) = 0; + virtual bool Inverse(double x,double y,double z,double &u,double &v) = 0; + virtual void Dfdu(double u, double v, double &x, double &y, double &z) = 0; + virtual void Dfdv(double u, double v, double &x, double &y, double &z) = 0; + virtual void Dfdfdudu(double u,double v,double &x,double &y,double &z) = 0; + virtual void Dfdfdudv(double u,double v,double &x,double &y,double &z) = 0; + virtual void Dfdfdvdv(double u,double v,double &x,double &y,double &z) = 0; + + // These functions may also be provided by the derived patches + // (usually for better performance), but they don't have to + virtual void Dndu(double u, double v, double &x, double &y, double &z); + virtual void Dndv(double u, double v, double &x, double &y, double &z); + virtual void GetUnitNormal(double u,double v,double &x,double &y,double &z); + virtual void GetNormal(double u, double v, double &x, double &y, double &z); + +}; + +#endif -- GitLab