Skip to content
Snippets Groups Projects
Commit b1b0c04c authored by Christophe Geuzaine's avatar Christophe Geuzaine
Browse files

- moved writeGEO() into the entity classes so that we can exploit

  kernel-specific information
- better documentation of lists returned by extrusions
parent ec677d53
Branches
Tags
No related merge requests found
......@@ -122,6 +122,33 @@ std::string GEdge::getAdditionalInfoString()
return sstream.str();
}
void GEdge::writeGEO(FILE *fp)
{
if(!getBeginVertex() || !getEndVertex() || geomType() == DiscreteCurve) return;
if(geomType() == Line){
fprintf(fp, "Line(%d) = {%d, %d};\n",
tag(), getBeginVertex()->tag(), getEndVertex()->tag());
}
else{
// approximate other curves by splines
Range<double> bounds = parBounds(0);
double umin = bounds.low();
double umax = bounds.high();
fprintf(fp, "p%d = newp;\n", tag());
for(int i = 1; i < minimumDrawSegments(); i++){
double u = umin + (double)i / minimumDrawSegments() * (umax - umin);
GPoint p = point(u);
fprintf(fp, "Point(p%d + %d) = {%.16g, %.16g, %.16g};\n",
tag(), i, p.x(), p.y(), p.z());
}
fprintf(fp, "Spline(%d) = {%d", tag(), getBeginVertex()->tag());
for(int i = 1; i < minimumDrawSegments(); i++)
fprintf(fp, ", p%d + %d", tag(), i);
fprintf(fp, ", %d};\n", getEndVertex()->tag());
}
}
bool GEdge::containsParam(double pt) const
{
Range<double> rg = parBounds(0);
......
......@@ -6,6 +6,7 @@
#ifndef _GEDGE_H_
#define _GEDGE_H_
#include <stdio.h>
#include "GEntity.h"
#include "GVertex.h"
#include "SVector3.h"
......@@ -95,6 +96,9 @@ class GEdge : public GEntity {
// return a type-specific additional information string
virtual std::string getAdditionalInfoString();
// export in GEO format
virtual void writeGEO(FILE *fp);
// tell if the edge is a 3D edge (in opposition with a trimmed curve on a surface)
virtual bool is3D() const { return true; }
......
......@@ -196,6 +196,38 @@ std::string GFace::getAdditionalInfoString()
return sstream.str();
}
void GFace::writeGEO(FILE *fp)
{
if(geomType() == DiscreteSurface) return;
std::list<GEdge*> edg = edges();
std::list<int> dir = orientations();
if(edg.size() && dir.size() == edg.size()){
std::vector<int> num, ori;
for(std::list<GEdge*>::iterator it = edg.begin(); it != edg.end(); it++)
num.push_back((*it)->tag());
for(std::list<int>::iterator it = dir.begin(); it != dir.end(); it++)
ori.push_back((*it) > 0 ? 1 : -1);
fprintf(fp, "Line Loop(%d) = ", tag());
for(unsigned int i = 0; i < num.size(); i++){
if(i)
fprintf(fp, ", %d", num[i] * ori[i]);
else
fprintf(fp, "{%d", num[i] * ori[i]);
}
fprintf(fp, "};\n");
if(geomType() == GEntity::Plane){
fprintf(fp, "Plane Surface(%d) = {%d};\n", tag(), tag());
}
else if(edg.size() == 3 || edg.size() == 4){
fprintf(fp, "Ruled Surface(%d) = {%d};\n", tag(), tag());
}
else{
Msg::Error("Skipping surface %d in export", tag());
}
}
}
void GFace::computeMeanPlane()
{
std::vector<SPoint3> pts;
......
......@@ -148,6 +148,9 @@ class GFace : public GEntity
// return a type-specific additional information string
virtual std::string getAdditionalInfoString();
// export in GEO format
virtual void writeGEO(FILE *fp);
// fill the crude representation cross
virtual bool buildRepresentationCross();
......
......@@ -194,191 +194,6 @@ class writeFieldGEO {
}
};
class writeGVertexGEO {
private :
FILE *geo;
public :
writeGVertexGEO(FILE *fp) { geo = fp ? fp : stdout; }
void operator() (GVertex *gv)
{
if(gv->getNativeType() == GEntity::GmshModel){
Vertex *v = (Vertex*)gv->getNativePtr();
if(!v) return;
fprintf(geo, "Point(%d) = {%.16g, %.16g, %.16g, %.16g};\n",
v->Num, v->Pos.X, v->Pos.Y, v->Pos.Z, v->lc);
}
else{
fprintf(geo, "Point(%d) = {%.16g, %.16g, %.16g, %.16g};\n",
gv->tag(), gv->x(), gv->y(), gv->z(),
gv->prescribedMeshSizeAtVertex());
}
}
};
class writeGEdgeGEO {
private :
FILE *geo;
public :
writeGEdgeGEO(FILE *fp) { geo = fp ? fp : stdout; }
void operator () (GEdge *ge)
{
if(ge->geomType() == GEntity::DiscreteCurve) return;
if(ge->getNativeType() == GEntity::GmshModel){
Curve *c = (Curve *)ge->getNativePtr();
if(!c || c->Num < 0) return;
switch (c->Typ) {
case MSH_SEGM_LINE:
fprintf(geo, "Line(%d) = ", c->Num);
break;
case MSH_SEGM_CIRC:
case MSH_SEGM_CIRC_INV:
fprintf(geo, "Circle(%d) = ", c->Num);
break;
case MSH_SEGM_ELLI:
case MSH_SEGM_ELLI_INV:
fprintf(geo, "Ellipse(%d) = ", c->Num);
break;
case MSH_SEGM_NURBS:
fprintf(geo, "Nurbs(%d) = {", c->Num);
for(int i = 0; i < List_Nbr(c->Control_Points); i++) {
Vertex *v;
List_Read(c->Control_Points, i, &v);
if(!i)
fprintf(geo, "%d", v->Num);
else
fprintf(geo, ", %d", v->Num);
if(i % 8 == 7 && i != List_Nbr(c->Control_Points) - 1)
fprintf(geo, "\n");
}
fprintf(geo, "}\n");
fprintf(geo, " Knots {");
for(int j = 0; j < List_Nbr(c->Control_Points) + c->degre + 1; j++) {
if(!j)
fprintf(geo, "%.16g", c->k[j]);
else
fprintf(geo, ", %.16g", c->k[j]);
if(j % 5 == 4 && j != List_Nbr(c->Control_Points) + c->degre)
fprintf(geo, "\n ");
}
fprintf(geo, "}\n");
fprintf(geo, " Order %d;\n", c->degre);
return;
case MSH_SEGM_SPLN:
fprintf(geo, "Spline(%d) = ", c->Num);
break;
case MSH_SEGM_BSPLN:
fprintf(geo, "BSpline(%d) = ", c->Num);
break;
case MSH_SEGM_BEZIER:
fprintf(geo, "Bezier(%d) = ", c->Num);
break;
default:
Msg::Error("Unknown curve type %d", c->Typ);
return;
}
for(int i = 0; i < List_Nbr(c->Control_Points); i++) {
Vertex *v;
List_Read(c->Control_Points, i, &v);
if(i)
fprintf(geo, ", %d", v->Num);
else
fprintf(geo, "{%d", v->Num);
if(i % 6 == 7)
fprintf(geo, "\n");
}
fprintf(geo, "};\n");
}
else{
if(ge->getBeginVertex() && ge->getEndVertex()){
if(ge->geomType() == GEntity::Line){
fprintf(geo, "Line(%d) = {%d, %d};\n",
ge->tag(), ge->getBeginVertex()->tag(), ge->getEndVertex()->tag());
}
else{
// approximate all other curves by splines
Range<double> bounds = ge->parBounds(0);
double umin = bounds.low();
double umax = bounds.high();
fprintf(geo, "p%d = newp;\n", ge->tag());
for(int i = 1; i < ge->minimumDrawSegments(); i++){
double u = umin + (double)i / ge->minimumDrawSegments() * (umax - umin);
GPoint p = ge->point(u);
fprintf(geo, "Point(p%d + %d) = {%.16g, %.16g, %.16g, 1.e+22};\n",
ge->tag(), i, p.x(), p.y(), p.z());
}
fprintf(geo, "Spline(%d) = {%d", ge->tag(), ge->getBeginVertex()->tag());
for(int i = 1; i < ge->minimumDrawSegments(); i++)
fprintf(geo, ", p%d + %d", ge->tag(), i);
fprintf(geo, ", %d};\n", ge->getEndVertex()->tag());
}
}
}
}
};
class writeGFaceGEO {
private :
FILE *geo;
public :
writeGFaceGEO(FILE *fp) { geo = fp ? fp : stdout; }
void operator () (GFace *gf)
{
if(gf->geomType() == GEntity::DiscreteSurface) return;
std::list<GEdge*> edges = gf->edges();
std::list<int> orientations = gf->orientations();
if(edges.size() && orientations.size() == edges.size()){
std::vector<int> num, ori;
for(std::list<GEdge*>::iterator it = edges.begin(); it != edges.end(); it++)
num.push_back((*it)->tag());
for(std::list<int>::iterator it = orientations.begin(); it != orientations.end(); it++)
ori.push_back((*it) > 0 ? 1 : -1);
fprintf(geo, "Line Loop(%d) = ", gf->tag());
for(unsigned int i = 0; i < num.size(); i++){
if(i)
fprintf(geo, ", %d", num[i] * ori[i]);
else
fprintf(geo, "{%d", num[i] * ori[i]);
}
fprintf(geo, "};\n");
if(gf->geomType() == GEntity::Plane){
fprintf(geo, "Plane Surface(%d) = {%d};\n", gf->tag(), gf->tag());
}
else if(edges.size() == 3 || edges.size() == 4){
fprintf(geo, "Ruled Surface(%d) = {%d};\n", gf->tag(), gf->tag());
}
else{
Msg::Error("Skipping surface %d in export", gf->tag());
}
}
}
};
class writeGRegionGEO {
private :
FILE *geo;
public :
writeGRegionGEO(FILE *fp) { geo = fp ? fp : stdout; }
void operator () (GRegion *gr)
{
if(gr->geomType() == GEntity::DiscreteVolume) return;
std::list<GFace*> faces = gr->faces();
if(faces.size()){
fprintf(geo, "Surface Loop(%d) = ", gr->tag());
for(std::list<GFace*>::iterator it = faces.begin(); it != faces.end(); it++) {
if(it != faces.begin())
fprintf(geo, ", %d", (*it)->tag());
else
fprintf(geo, "{%d", (*it)->tag());
}
fprintf(geo, "};\n");
fprintf(geo, "Volume(%d) = {%d};\n", gr->tag(), gr->tag());
}
}
};
class writePhysicalGroupGEO {
private :
FILE *geo;
......@@ -431,10 +246,14 @@ int GModel::writeGEO(const std::string &name, bool printLabels)
{
FILE *fp = fopen(name.c_str(), "w");
std::for_each(firstVertex(), lastVertex(), writeGVertexGEO(fp));
std::for_each(firstEdge(), lastEdge(), writeGEdgeGEO(fp));
std::for_each(firstFace(), lastFace(), writeGFaceGEO(fp));
std::for_each(firstRegion(), lastRegion(), writeGRegionGEO(fp));
for(viter it = firstVertex(); it != lastVertex(); it++)
(*it)->writeGEO(fp);
for(eiter it = firstEdge(); it != lastEdge(); it++)
(*it)->writeGEO(fp);
for(fiter it = firstFace(); it != lastFace(); it++)
(*it)->writeGEO(fp);
for(riter it = firstRegion(); it != lastRegion(); it++)
(*it)->writeGEO(fp);
std::map<int, std::string> labels;
#if !defined(HAVE_NO_PARSER)
......
......@@ -136,6 +136,23 @@ std::string GRegion::getAdditionalInfoString()
return sstream.str();
}
void GRegion::writeGEO(FILE *fp)
{
if(geomType() == DiscreteVolume) return;
if(l_faces.size()){
fprintf(fp, "Surface Loop(%d) = ", tag());
for(std::list<GFace*>::iterator it = l_faces.begin(); it != l_faces.end(); it++) {
if(it != l_faces.begin())
fprintf(fp, ", %d", (*it)->tag());
else
fprintf(fp, "{%d", (*it)->tag());
}
fprintf(fp, "};\n");
fprintf(fp, "Volume(%d) = {%d};\n", tag(), tag());
}
}
std::list<GEdge*> GRegion::edges() const
{
std::list<GEdge*> e;
......
......@@ -6,6 +6,7 @@
#ifndef _GREGION_H_
#define _GREGION_H_
#include <stdio.h>
#include "GEntity.h"
class MElement;
......@@ -51,6 +52,9 @@ class GRegion : public GEntity {
// return a type-specific additional information string
virtual std::string getAdditionalInfoString();
// export in GEO format
virtual void writeGEO(FILE *fp);
// number of types of elements
int getNumElementTypes() const { return 4; }
......
......@@ -56,6 +56,12 @@ std::string GVertex::getAdditionalInfoString()
return sstream.str();
}
void GVertex::writeGEO(FILE *fp)
{
fprintf(fp, "Point(%d) = {%.16g, %.16g, %.16g, %.16g};\n",
tag(), x(), y(), z(), prescribedMeshSizeAtVertex());
}
unsigned int GVertex::getNumMeshElements()
{
return points.size();
......
......@@ -6,6 +6,7 @@
#ifndef _GVERTEX_H_
#define _GVERTEX_H_
#include <stdio.h>
#include "GEntity.h"
#include "GPoint.h"
#include "SPoint2.h"
......@@ -39,6 +40,9 @@ class GVertex : public GEntity
void addEdge(GEdge *e);
void delEdge(GEdge *e);
// get the edges that this vertex bounds
virtual std::list<GEdge*> edges() const{ return l_edges; }
// get the dimension of the vertex (0)
virtual int dim() const { return 0; }
......@@ -58,8 +62,8 @@ class GVertex : public GEntity
// return a type-specific additional information string
virtual std::string getAdditionalInfoString();
// get the edges that this vertex bounds
virtual std::list<GEdge*> edges() const{ return l_edges; }
// export in GEO format
virtual void writeGEO(FILE *fp);
// get number of elements in the mesh
unsigned int getNumMeshElements();
......
......@@ -30,23 +30,6 @@ OCCEdge::OCCEdge(GModel *model, TopoDS_Edge edge, int num, GVertex *v1, GVertex
// build the reverse curve
c_rev = c;
c_rev.Reverse();
// if (v0 == v1){
// const int JJ = 52;
// for (int i=1;i<JJ;i++){
// const double t = i/((double) JJ);
// const double xi = s0 + (s1-s0) * t;
// GPoint p = point(xi);
// MEdgeVertex *v = new MEdgeVertex (p.x(),p.y(),p.z(),this,xi);
// mesh_vertices.push_back(v);
// meshAttributes.Method = MESH_NONE;
// if (i == 1)lines.push_back(new MLine(v1->mesh_vertices[0],v));
// else if (i == JJ-1)lines.push_back(new MLine(v,v2->mesh_vertices[0]));
// else lines.push_back(new MLine(mesh_vertices[i-1],v));
// }
// }
}
Range<double> OCCEdge::parBounds(int i) const
......@@ -243,19 +226,32 @@ double OCCEdge::curvature(double par) const
Crv = prop.Curvature();
}
if(Crv <= eps) Crv = eps;
// std::list<GFace*> ff = faces();
// std::list<GFace *>::iterator it = ff.begin();
// while (it != ff.end()){
// SPoint2 par2 = reparamOnFace((*it),par,1);
// const double cc = (*it)->curvature ( par2 );
// if (cc > 0)
// Crv = std::max( Crv, cc);
// ++it;
// }
// printf("curvature = %12.5E\n",Crv);
return Crv;
}
void OCCEdge::writeGEO(FILE *fp)
{
if(geomType() == Circle){
gp_Pnt center;
if(curve.IsNull()){
center = Handle(Geom_Circle)::DownCast(curve2d)->Location();
}
else{
center = Handle(Geom_Circle)::DownCast(curve)->Location();
}
// GEO supports only circle arcs < Pi
if(s1 - s0 < M_PI){
fprintf(fp, "p%d = newp;\n", tag());
fprintf(fp, "Point(p%d + 1) = {%.16g, %.16g, %.16g};\n",
tag(), center.X(), center.Y(), center.Z());
fprintf(fp, "Circle(%d) = {%d, p%d + 1, %d};\n",
tag(), getBeginVertex()->tag(), tag(), getEndVertex()->tag());
}
else
GEdge::writeGEO(fp);
}
else
GEdge::writeGEO(fp);
}
#endif
......@@ -41,6 +41,7 @@ class OCCEdge : public GEdge {
bool is3D() const { return !curve.IsNull(); }
void setTrimmed(OCCFace *);
bool isSeam(const GFace *) const;
virtual void writeGEO(FILE *fp);
};
#endif
......
......@@ -258,3 +258,69 @@ SPoint2 gmshEdge::reparamOnFace(const GFace *face, double epar,int dir) const
else
return GEdge::reparamOnFace(face, epar, dir);
}
void gmshEdge::writeGEO(FILE *fp)
{
if(!c || c->Num < 0 || c->Typ == MSH_SEGM_DISCRETE) return;
switch (c->Typ) {
case MSH_SEGM_LINE:
fprintf(fp, "Line(%d) = ", c->Num);
break;
case MSH_SEGM_CIRC:
case MSH_SEGM_CIRC_INV:
fprintf(fp, "Circle(%d) = ", c->Num);
break;
case MSH_SEGM_ELLI:
case MSH_SEGM_ELLI_INV:
fprintf(fp, "Ellipse(%d) = ", c->Num);
break;
case MSH_SEGM_NURBS:
fprintf(fp, "Nurbs(%d) = {", c->Num);
for(int i = 0; i < List_Nbr(c->Control_Points); i++) {
Vertex *v;
List_Read(c->Control_Points, i, &v);
if(!i)
fprintf(fp, "%d", v->Num);
else
fprintf(fp, ", %d", v->Num);
if(i % 8 == 7 && i != List_Nbr(c->Control_Points) - 1)
fprintf(fp, "\n");
}
fprintf(fp, "}\n");
fprintf(fp, " Knots {");
for(int j = 0; j < List_Nbr(c->Control_Points) + c->degre + 1; j++) {
if(!j)
fprintf(fp, "%.16g", c->k[j]);
else
fprintf(fp, ", %.16g", c->k[j]);
if(j % 5 == 4 && j != List_Nbr(c->Control_Points) + c->degre)
fprintf(fp, "\n ");
}
fprintf(fp, "}\n");
fprintf(fp, " Order %d;\n", c->degre);
return;
case MSH_SEGM_SPLN:
fprintf(fp, "Spline(%d) = ", c->Num);
break;
case MSH_SEGM_BSPLN:
fprintf(fp, "BSpline(%d) = ", c->Num);
break;
case MSH_SEGM_BEZIER:
fprintf(fp, "Bezier(%d) = ", c->Num);
break;
default:
Msg::Error("Unknown curve type %d", c->Typ);
return;
}
for(int i = 0; i < List_Nbr(c->Control_Points); i++) {
Vertex *v;
List_Read(c->Control_Points, i, &v);
if(i)
fprintf(fp, ", %d", v->Num);
else
fprintf(fp, "{%d", v->Num);
if(i % 6 == 7)
fprintf(fp, "\n");
}
fprintf(fp, "};\n");
}
......@@ -26,6 +26,7 @@ class gmshEdge : public GEdge {
virtual int minimumDrawSegments() const;
virtual void resetMeshAttributes();
virtual SPoint2 reparamOnFace(const GFace *face, double epar, int dir) const;
virtual void writeGEO(FILE *fp);
};
#endif
......@@ -97,3 +97,9 @@ SPoint2 gmshVertex::reparamOnFace(const GFace *face, int dir) const
return GVertex::reparamOnFace(face, dir);
}
}
void gmshVertex::writeGEO(FILE *fp)
{
fprintf(fp, "Point(%d) = {%.16g, %.16g, %.16g, %.16g};\n",
v->Num, v->Pos.X, v->Pos.Y, v->Pos.Z, v->lc);
}
......@@ -33,6 +33,7 @@ class gmshVertex : public GVertex {
v->lc = meshSize;
}
virtual SPoint2 reparamOnFace(const GFace *gf, int) const;
virtual void writeGEO(FILE *fp);
};
#endif
......@@ -1001,9 +1001,6 @@ of a given geometry point (@pxref{Points}). The last two cases permit to
retrieve the indices of entities created through geometrical transformations
and extrusions (see @ref{Transformations}, and @ref{Extrusions}).
@c todo: explain in detail what numbers are returned once we decide what to
@c do (chapeau et body pour extrude, etc.)...
To see the practical use of such expressions, have a look at the first
couple of examples in @ref{Tutorial}. Note that, in order to lighten the
syntax, you can always omit the braces @code{@{@}} enclosing an
......@@ -1971,6 +1968,26 @@ the X, Y and Z components of any point on this axis; the last
Point | Line | Surface @{ @var{expression-list} @}; @dots{}
@end example
As explained in @ref{Floating point expressions}, @var{extrude} can be
used in an expression, in which case it returns a list of identification
numbers. By default, the list contains the ``top'' of the extruded
entity at index 0 and the extruded entity at index 1, followed by the
``sides'' of the extruded entity at indices 2, 3, etc. For example:
@example
Point(1) = @{0,0,0@};
Point(2) = @{1,0,0@};
Line(1) = @{1, 2@};
out[] = Extrude@{0,1,0@}@{ Line@{1@}; @};
Printf("top line = %g", out[0]);
Printf("surface = %g", out[1]);
Printf("side lines = %g and %g", out[2], out[3]);
@end example
This behaviour can be changed with the
@code{Geometry.ExtrudeReturnLateralEntities} option (@pxref{Geometry
options list}).
@c .........................................................................
@c Transformations
@c .........................................................................
......@@ -3155,7 +3172,7 @@ the nodes is given in @ref{Node ordering}.
@item @var{number-of-string-tags}
gives the number of string tags that follow. By default the first
@var{string-tag} is interpreted as the name of the post-processing view.
@c FIXME and the second as the name of the interpolation scheme.
@c todo: and the second as the name of the interpolation scheme?
@item @var{number-of-real-tags}
gives the number of real number tags that follow. By default the first
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment