Forked from
gmsh / gmsh
18207 commits behind the upstream repository.
-
Christophe Geuzaine authoredChristophe Geuzaine authored
Geom.cpp 21.73 KiB
// $Id: Geom.cpp,v 1.93 2005-10-10 16:16:50 geuzaine Exp $
//
// Copyright (C) 1997-2005 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>.
#include "BDS.h"
#include "Gmsh.h"
#include "GmshUI.h"
#include "Numeric.h"
#include "Geo.h"
#include "CAD.h"
#include "Mesh.h"
#include "Utils.h"
#include "Draw.h"
#include "Context.h"
#include "Interpolation.h"
#include "Plugin.h"
#include "PluginManager.h"
#include "gl2ps.h"
extern Context_T CTX;
extern Mesh *THEM;
// Points
void Draw_Geo_Point(void *a, void *b)
{
char Num[100];
Vertex *v = *(Vertex **) a;
if(!(v->Visible & VIS_GEOM))
return;
if(CTX.render_mode == GMSH_SELECT) {
glLoadName(0);
glPushName(v->Num);
}
if(v->Frozen) {
glPointSize(CTX.geom.point_sel_size);
gl2psPointSize(CTX.geom.point_sel_size * CTX.print.eps_point_size_factor);
glColor4ubv((GLubyte *) & CTX.color.geom.point_sel);
}
else {
glPointSize(CTX.geom.point_size);
gl2psPointSize(CTX.geom.point_size * CTX.print.eps_point_size_factor);
glColor4ubv((GLubyte *) & CTX.color.geom.point);
}
if(CTX.geom.points) {
if(CTX.geom.point_type == 1) {
if(v->Frozen)
Draw_Sphere(CTX.geom.point_sel_size, v->Pos.X, v->Pos.Y, v->Pos.Z,
CTX.geom.light);
else
Draw_Sphere(CTX.geom.point_size, v->Pos.X, v->Pos.Y, v->Pos.Z,
CTX.geom.light);
}
else if(CTX.geom.point_type == 2) {
GMSH_Solve_Plugin *sp = GMSH_PluginManager::instance()->findSolverPlugin();
if(sp) {
sp-> GL_enhancePoint (v);
}
glBegin(GL_POINTS);
glVertex3d(v->Pos.X, v->Pos.Y, v->Pos.Z);
glEnd();
}
else {
glBegin(GL_POINTS);
glVertex3d(v->Pos.X, v->Pos.Y, v->Pos.Z);
glEnd();
}
}
if(CTX.geom.points_num) {
sprintf(Num, "%d", v->Num);
double offset = (0.5 * CTX.geom.point_size + 0.3 * CTX.gl_fontsize) * CTX.pixel_equiv_x;
glRasterPos3d(v->Pos.X + offset / CTX.s[0],
v->Pos.Y + offset / CTX.s[1],
v->Pos.Z + offset / CTX.s[2]);
Draw_String(Num);
}
if(CTX.render_mode == GMSH_SELECT) {
glPopName();
}
}
// Curves
void Draw_Curve(void *a, void *b)
{
int N;
double mod, x[2], y[2], z[2];
char Num[100];
Vertex v, dv;
Curve *c = *(Curve **) a;
if(c->Num < 0 || !(c->Visible & VIS_GEOM))
return;
if(CTX.render_mode == GMSH_SELECT) {
glLoadName(1);
glPushName(c->Num);
}
if(c->ipar[3] > 0) {
glLineWidth(CTX.geom.line_sel_width);
gl2psLineWidth(CTX.geom.line_sel_width * CTX.print.eps_line_width_factor);
glColor4ubv((GLubyte *) & CTX.color.geom.line_sel);
}
else {
glLineWidth(CTX.geom.line_width);
gl2psLineWidth(CTX.geom.line_width * CTX.print.eps_line_width_factor);
glColor4ubv((GLubyte *) & CTX.color.geom.line);
}
if(CTX.geom.lines) {
int n = List_Nbr(c->Control_Points);
switch (c->Typ) {
case MSH_SEGM_LINE:
N = n;
break;
case MSH_SEGM_CIRC:
case MSH_SEGM_CIRC_INV:
case MSH_SEGM_ELLI:
case MSH_SEGM_ELLI_INV:
N = CTX.geom.circle_points;
break;
default:
N = 10 * n;
break;
}
if(c->Typ == MSH_SEGM_DISCRETE && THEM->bds) {
BDS_GeomEntity *g = THEM->bds->get_geom ( c->Num,1);
std::list<BDS_Edge*>::iterator it = g->e.begin();
std::list<BDS_Edge*>::iterator ite = g->e.end();
while (it!=ite){
BDS_Edge *e = (*it);
if(CTX.geom.line_type < 1) {
glBegin(GL_LINES);
glVertex3d(e->p1->X,e->p1->Y,e->p1->Z);
glVertex3d(e->p2->X,e->p2->Y,e->p2->Z);
glEnd();
}
else
{
x[0] = e->p1->X;
y[0] = e->p1->Y;
z[0] = e->p1->Z;
x[1] = e->p2->X;
y[1] = e->p2->Y;
z[1] = e->p2->Z;
Draw_Cylinder(c->ipar[3] > 0 ? CTX.geom.line_sel_width : CTX.geom.line_width,
x, y, z, CTX.geom.light);
}
++it;
}
}
else if(c->Typ == MSH_SEGM_DISCRETE) {
// do nothing: we draw the elements in the mesh drawing routines
}
else {
if(CTX.geom.line_type >= 1) {
for(int i = 0; i < N - 1; i++) {
v = InterpolateCurve(c, (double)i / (double)(N - 1), 0);
dv = InterpolateCurve(c, (double)(i + 1) / (double)(N - 1), 0);
x[0] = v.Pos.X;
y[0] = v.Pos.Y;
z[0] = v.Pos.Z;
x[1] = dv.Pos.X;
y[1] = dv.Pos.Y;
z[1] = dv.Pos.Z;
Draw_Cylinder(c->ipar[3] > 0 ? CTX.geom.line_sel_width : CTX.geom.line_width,
x, y, z, CTX.geom.light);
}
if(CTX.geom.line_type == 2) {
GMSH_Solve_Plugin *sp = GMSH_PluginManager::instance()->findSolverPlugin();
if(sp) {
int NN=(N>1)?N:1;
const double eps=0.e-2;
for(int i = 0; i < NN - 1; i++) {
v = InterpolateCurve(c, (double)i / (double)(NN - 1)-eps, 0);
dv = InterpolateCurve(c, (double)(i + 1) / (double)(NN - 1)+eps, 0);
sp-> GL_enhanceLine (c->Num,&v,&dv);
}
}
}
}
else {
glBegin(GL_LINE_STRIP);
for(int i = 0; i < N; i++) {
v = InterpolateCurve(c, (double)i / (double)(N - 1), 0);
glVertex3d(v.Pos.X, v.Pos.Y, v.Pos.Z);
}
glEnd();
}
}
}
if(CTX.geom.lines_num) {
v = InterpolateCurve(c, 0.5, 0);
sprintf(Num, "%d", c->Num);
double offset = (0.5 * CTX.geom.line_width + 0.3 * CTX.gl_fontsize) * CTX.pixel_equiv_x;
glRasterPos3d(v.Pos.X + offset / CTX.s[0],
v.Pos.Y + offset / CTX.s[1],
v.Pos.Z + offset / CTX.s[2]);
Draw_String(Num);
}
if(CTX.geom.tangents) {
v = InterpolateCurve(c, 0.5, 0);
dv = InterpolateCurve(c, 0.5, 1);
mod = sqrt(dv.Pos.X * dv.Pos.X + dv.Pos.Y * dv.Pos.Y + dv.Pos.Z * dv.Pos.Z);
dv.Pos.X = dv.Pos.X / mod * CTX.geom.tangents * CTX.pixel_equiv_x / CTX.s[0];
dv.Pos.Y = dv.Pos.Y / mod * CTX.geom.tangents * CTX.pixel_equiv_x / CTX.s[1];
dv.Pos.Z = dv.Pos.Z / mod * CTX.geom.tangents * CTX.pixel_equiv_x / CTX.s[2];
glColor4ubv((GLubyte *) & CTX.color.geom.tangents);
Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius,
CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
v.Pos.X, v.Pos.Y, v.Pos.Z,
dv.Pos.X, dv.Pos.Y, dv.Pos.Z, CTX.geom.light);
}
if(CTX.render_mode == GMSH_SELECT) {
glPopName();
}
}
// Surfaces
void putZ(Vertex * v, Surface * s)
{
Vertex V;
V.Pos.X = s->a;
V.Pos.Y = s->b;
V.Pos.Z = s->c;
Projette(&V, s->plan);
if(V.Pos.Z != 0.0)
v->Pos.Z = (s->d - V.Pos.X * v->Pos.X - V.Pos.Y * v->Pos.Y) / V.Pos.Z;
else
v->Pos.Z = 0.0;
Projette(v, s->invplan);
}
int isPointOnPlanarSurface(Surface * S, double X, double Y, double Z,
double n[3])
{
double Angle = 0.0;
Vertex V;
V.Pos.X = X;
V.Pos.Y = Y;
V.Pos.Z = Z;
for(int i = 0; i < List_Nbr(S->Generatrices); i++) {
Curve *C;
List_Read(S->Generatrices, i, &C);
int N = (C->Typ == MSH_SEGM_LINE) ? 1 : 10;
for(int j = 0; j < N; j++) {
double u1 = (double)j / (double)(N);
double u2 = (double)(j + 1) / (double)(N);
Vertex P1 = InterpolateCurve(C, u1, 0);
Vertex P2 = InterpolateCurve(C, u2, 0);
Angle += angle_plan(&V, &P1, &P2, n);
}
}
// if Angle == 2*pi, we're inside
if(fabs(Angle) > 2*M_PI-0.5 && fabs(Angle) < 2*M_PI+0.5)
return 1;
return 0;
}
void getPlaneSurfaceNormal(Surface *s, double x, double y, double z, double n[3])
{
double t1[3], t2[3];
Curve *c;
for(int i = 0; i < 3; i++)
n[i] = 0.0;
if(s->Typ != MSH_SURF_PLAN)
return;
// We cannot use s->plan or InterpolateSurface here (they both rely
// on the mean plane, which borks the orientation). So we need to
// use this trick:
if(List_Nbr(s->Generatrices) > 1){
List_Read(s->Generatrices, 0, &c);
if(c->beg){
t1[0] = x - c->beg->Pos.X;
t1[1] = y - c->beg->Pos.Y;
t1[2] = z - c->beg->Pos.Z;
// 1) try to get a point close to 'beg' on the same curve
// 2) if we are really unlucky and these two points are aligned
// with (x,y,z), which we know is inside or on the boundary of
// the surface, then get a point from the next generatrice
// 3) repeat
for(int i = 0; i < List_Nbr(s->Generatrices); i++){
List_Read(s->Generatrices, i, &c);
Vertex v = InterpolateCurve(c, 0.1, 0);
t2[0] = x - v.Pos.X;
t2[1] = y - v.Pos.Y;
t2[2] = z - v.Pos.Z;
prodve(t1, t2, n);
if(norme(n))
break;
}
}
}
if(List_Nbr(s->Generatrices) < 2 || !norme(n)){
Msg(WARNING, "Reverting to mean plane normal for surface %d", s->Num);
n[0] = s->a;
n[1] = s->b;
n[2] = s->c;
norme(n);
}
}
void Draw_Polygonal_Surface(Surface * s)
{
if(CTX.geom.surfaces) {
if(CTX.geom.light) glEnable(GL_LIGHTING);
glEnable(GL_POLYGON_OFFSET_FILL); // always!
BDS_GeomEntity *g = THEM->bds->get_geom ( s->Num,2);
// if (g->surf) glColor4ubv((GLubyte *) & CTX.color.geom.line);
std::list<BDS_Triangle*>::iterator it = g->t.begin();
std::list<BDS_Triangle*>::iterator ite = g->t.end();
while (it!=ite) {
glBegin(GL_TRIANGLES);
BDS_Point *n[3];
BDS_Triangle *t = (*it);
double c[3];
t->getNodes (n);
normal_triangle (n[0],n[1],n[2],c);
if(CTX.geom.light) glNormal3dv(c);
glVertex3d(n[0]->X,n[0]->Y,n[0]->Z);
if(CTX.geom.light) glNormal3dv(c);
glVertex3d(n[1]->X,n[1]->Y,n[1]->Z);
if(CTX.geom.light) glNormal3dv(c);
glVertex3d(n[2]->X,n[2]->Y,n[2]->Z);
glEnd();
++it;
}
glDisable(GL_POLYGON_OFFSET_FILL);
glDisable(GL_LIGHTING);
}
}
void Draw_Plane_Surface(Surface * s)
{
Curve *c;
Vertex V[4], vv, vv1, vv2;
double n[3];
if(!CTX.threads_lock && List_Nbr(s->Orientations) < 1) {
CTX.threads_lock = 1;
List_T *points = List_Create(10, 10, sizeof(Vertex *));
for(int i = 0; i < List_Nbr(s->Generatrices); i++) {
List_Read(s->Generatrices, i, &c);
for(int j = 0; j < List_Nbr(c->Control_Points); j++) {
List_Add(points, List_Pointer(c->Control_Points, j));
}
}
if(!List_Nbr(points)){
List_Delete(points);
CTX.threads_lock = 0;
return;
}
MeanPlane(points, s);
List_Delete(points);
// compute (rough) bounding box of surface
double minx = 0., miny = 0., maxx = 0., maxy = 0.;
for(int i = 0; i < List_Nbr(s->Generatrices); i++) {
List_Read(s->Generatrices, i, &c);
Vertex P1 = InterpolateCurve(c, 0.0, 0);
Vertex P2 = InterpolateCurve(c, 0.5, 0);
Vertex P3 = InterpolateCurve(c, 1.0, 0);
Projette(&P1, s->plan);
Projette(&P2, s->plan);
Projette(&P3, s->plan);
if(!i) {
minx = maxx = P1.Pos.X;
miny = maxy = P1.Pos.Y;
}
minx = DMIN(DMIN(DMIN(minx, P1.Pos.X), P2.Pos.X), P3.Pos.X);
miny = DMIN(DMIN(DMIN(miny, P1.Pos.Y), P2.Pos.Y), P3.Pos.Y);
maxx = DMAX(DMAX(DMAX(maxx, P1.Pos.X), P2.Pos.X), P3.Pos.X);
maxy = DMAX(DMAX(DMAX(maxy, P1.Pos.Y), P2.Pos.Y), P3.Pos.Y);
}
V[0].Pos.X = minx;
V[0].Pos.Y = miny;
V[1].Pos.X = maxx;
V[1].Pos.Y = miny;
V[2].Pos.X = maxx;
V[2].Pos.Y = maxy;
V[3].Pos.X = minx;
V[3].Pos.Y = maxy;
for(int i = 0; i < 4; i++) {
V[i].Pos.Z = 0.0;
putZ(&V[i], s);
}
n[0] = s->plan[2][0];
n[1] = s->plan[2][1];
n[2] = s->plan[2][2];
norme(n);
// compute which parts of the "middle cross" lie inside the surface
const int numPoints = 200;
for(int cross = 0; cross < 2; cross++) {
int k = 0;
for(int i = 0; i < numPoints; i++) {
double t = (double)i / (double)(numPoints-1);
if(!cross){
vv.Pos.X = t * 0.5 * (V[0].Pos.X + V[1].Pos.X) +
(1. - t) * 0.5 * (V[2].Pos.X + V[3].Pos.X);
vv.Pos.Y = t * 0.5 * (V[0].Pos.Y + V[1].Pos.Y) +
(1. - t) * 0.5 * (V[2].Pos.Y + V[3].Pos.Y);
vv.Pos.Z = t * 0.5 * (V[0].Pos.Z + V[1].Pos.Z) +
(1. - t) * 0.5 * (V[2].Pos.Z + V[3].Pos.Z);
}
else{
vv.Pos.X = t * .5 * (V[0].Pos.X + V[3].Pos.X) +
(1. - t) * .5 * (V[2].Pos.X + V[1].Pos.X);
vv.Pos.Y = t * .5 * (V[0].Pos.Y + V[3].Pos.Y) +
(1. - t) * .5 * (V[2].Pos.Y + V[1].Pos.Y);
vv.Pos.Z = t * .5 * (V[0].Pos.Z + V[3].Pos.Z) +
(1. - t) * .5 * (V[2].Pos.Z + V[1].Pos.Z);
}
if(isPointOnPlanarSurface(s, vv.Pos.X, vv.Pos.Y, vv.Pos.Z, n)) {
if(!k) {
List_Add(s->Orientations, &vv);
k = 1;
}
}
else {
if(k) {
List_Add(s->Orientations, &vv);
k = 0;
}
}
}
if(k)
List_Add(s->Orientations, &vv);
}
Msg(STATUS2, "Plane Surface %d (%d cross points)",
s->Num, List_Nbr(s->Orientations));
if(!List_Nbr(s->Orientations)){ // add dummy
List_Add(s->Orientations, &vv);
//printf("surf %d: min=%g %g max=%g %g\n", s->Num, minx, miny, maxx, maxy);
}
CTX.threads_lock = 0;
}
if(List_Nbr(s->Orientations) > 1) {
if(CTX.geom.surfaces) {
glEnable(GL_LINE_STIPPLE);
glLineStipple(1, 0x1F1F);
gl2psEnable(GL2PS_LINE_STIPPLE);
glBegin(GL_LINES);
for(int i = 0; i < List_Nbr(s->Orientations); i++) {
List_Read(s->Orientations, i, &vv);
glVertex3d(vv.Pos.X, vv.Pos.Y, vv.Pos.Z);
}
glEnd();
glDisable(GL_LINE_STIPPLE);
gl2psDisable(GL2PS_LINE_STIPPLE);
}
if(CTX.geom.surfaces_num) {
List_Read(s->Orientations, 0, &vv1);
List_Read(s->Orientations, 1, &vv2);
char Num[100];
sprintf(Num, "%d", s->Num);
double offset = 0.3 * CTX.gl_fontsize * CTX.pixel_equiv_x;
glRasterPos3d((vv2.Pos.X + vv1.Pos.X) / 2. + offset / CTX.s[0],
(vv2.Pos.Y + vv1.Pos.Y) / 2. + offset / CTX.s[1],
(vv2.Pos.Z + vv1.Pos.Z) / 2. + offset / CTX.s[2]);
Draw_String(Num);
}
if(CTX.geom.normals) {
List_Read(s->Orientations, 0, &vv1);
List_Read(s->Orientations, 1, &vv2);
double x = (vv1.Pos.X + vv2.Pos.X) / 2.;
double y = (vv1.Pos.Y + vv2.Pos.Y) / 2.;
double z = (vv1.Pos.Z + vv2.Pos.Z) / 2.;
getPlaneSurfaceNormal(s, x, y, z, n);
n[0] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[0];
n[1] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[1];
n[2] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[2];
glColor4ubv((GLubyte *) & CTX.color.geom.normals);
Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius,
CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
x, y, z, n[0], n[1], n[2], CTX.geom.light);
}
}
}
void Draw_NonPlane_Surface(Surface * s)
{
if(CTX.geom.surfaces) {
if(s->Typ == MSH_SURF_NURBS) {
if(CTX.geom.light) glEnable(GL_LIGHTING);
if(CTX.polygon_offset) glEnable(GL_POLYGON_OFFSET_FILL);
GLUnurbsObj *nurb;
nurb = gluNewNurbsRenderer();
#if defined(GLU_VERSION_1_3)
gluNurbsProperty(nurb, (GLenum) GLU_SAMPLING_TOLERANCE, 50.0);
gluNurbsProperty(nurb, (GLenum) GLU_DISPLAY_MODE, GLU_FILL);
#endif
gluBeginSurface(nurb);
gluNurbsSurface(nurb, s->Nu + s->OrderU + 1, s->ku,
s->Nv + s->OrderV + 1, s->kv, 4, 4 * s->Nu, s->cp,
s->OrderU + 1, s->OrderV + 1, GL_MAP2_VERTEX_4);
gluEndSurface(nurb);
gluDeleteNurbsRenderer(nurb);
glDisable(GL_POLYGON_OFFSET_FILL);
glDisable(GL_LIGHTING);
}
else{
glEnable(GL_LINE_STIPPLE);
glLineStipple(1, 0x1F1F);
gl2psEnable(GL2PS_LINE_STIPPLE);
int N = 50;
glBegin(GL_LINE_STRIP);
for(int i = 0; i < N + 1; i++) {
double u = (double)i / (double)N;
Vertex v = InterpolateSurface(s, u, 0.5, 0, 0);
glVertex3d(v.Pos.X, v.Pos.Y, v.Pos.Z);
}
glEnd();
glBegin(GL_LINE_STRIP);
for(int i = 0; i < N + 1; i++) {
double u = (double)i / (double)N;
Vertex v = InterpolateSurface(s, 0.5, u, 0, 0);
glVertex3d(v.Pos.X, v.Pos.Y, v.Pos.Z);
}
glEnd();
glDisable(GL_LINE_STIPPLE);
gl2psDisable(GL2PS_LINE_STIPPLE);
}
}
if(CTX.geom.surfaces_num) {
Vertex v = InterpolateSurface(s, 0.5, 0.5, 0, 0);
char Num[100];
sprintf(Num, "%d", s->Num);
double offset = 0.3 * CTX.gl_fontsize * CTX.pixel_equiv_x;
glRasterPos3d(v.Pos.X + offset / CTX.s[0],
v.Pos.Y + offset / CTX.s[1],
v.Pos.Z + offset / CTX.s[2]);
Draw_String(Num);
}
if(CTX.geom.normals) {
Vertex v1 = InterpolateSurface(s, 0.5, 0.5, 0, 0);
Vertex v2 = InterpolateSurface(s, 0.6, 0.5, 0, 0);
Vertex v3 = InterpolateSurface(s, 0.5, 0.6, 0, 0);
double n[3];
normal3points(v1.Pos.X, v1.Pos.Y, v1.Pos.Z,
v2.Pos.X, v2.Pos.Y, v2.Pos.Z,
v3.Pos.X, v3.Pos.Y, v3.Pos.Z, n);
n[0] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[0];
n[1] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[1];
n[2] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[2];
glColor4ubv((GLubyte *) & CTX.color.geom.normals);
Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius,
CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
v1.Pos.X, v1.Pos.Y, v1.Pos.Z, n[0], n[1], n[2],
CTX.geom.light);
}
}
void Draw_Surface(void *a, void *b)
{
Surface *s = *(Surface **) a;
if(!s || !s->Support || !(s->Visible & VIS_GEOM))
return;
if(CTX.render_mode == GMSH_SELECT) {
glLoadName(2);
glPushName(s->Num);
}
if(s->ipar[4] > 0) {
glLineWidth(CTX.geom.line_sel_width / 2.);
gl2psLineWidth(CTX.geom.line_sel_width / 2. *
CTX.print.eps_line_width_factor);
glColor4ubv((GLubyte *) & CTX.color.geom.surface_sel);
}
else {
glLineWidth(CTX.geom.line_width / 2.);
gl2psLineWidth(CTX.geom.line_width / 2. * CTX.print.eps_line_width_factor);
glColor4ubv((GLubyte *) & CTX.color.geom.surface);
}
if(THEM->bds){
Draw_Polygonal_Surface(s);
}
else if(s->Typ == MSH_SURF_DISCRETE){
// do nothing: we draw the elements in the mesh drawing routines
}
else if(s->Typ == MSH_SURF_PLAN){
Draw_Plane_Surface(s);
}
else{
Draw_NonPlane_Surface(s);
}
if(CTX.render_mode == GMSH_SELECT) {
glPopName();
}
}
// Volumes
void DrawVolumes(Mesh * m)
{
}
// Draw geometry
void Draw_Geom(Mesh * m)
{
if(m->status == -1)
return;
if(CTX.geom.points || CTX.geom.points_num)
Tree_Action(m->Points, Draw_Geo_Point);
if(CTX.geom.lines || CTX.geom.lines_num || CTX.geom.tangents)
Tree_Action(m->Curves, Draw_Curve);
if(CTX.geom.surfaces || CTX.geom.surfaces_num || CTX.geom.normals)
Tree_Action(m->Surfaces, Draw_Surface);
if(CTX.geom.volumes || CTX.geom.volumes_num)
DrawVolumes(m);
}
// Highlight routines
void HighlightEntity(Vertex * v, Curve * c, Surface * s, int permanent)
{
Curve *cc;
char Message[256], temp[256];
// Note: in Gmsh < 1.61, we used to draw permanent highlights (the
// "red" selected lines, etc.) using incremental drawing, i.e., by
// drawing "over" the current picture in-between Draw() calls. This
// was fine for simple overlays on points and lines (that we could
// draw with a slightly larger width so that they would cover the
// old ones), but it does not work well when drawing surfaces,
// post-pro views, etc. And since real cross-platform overlays are
// unmanageable, the best solution is actually to redraw the whole
// scene. This is the approach we follow now.
if(v) {
if(permanent){
v->Frozen = 1;
}
else{
Msg(STATUS1N, "Point %d {%.5g,%.5g,%.5g} (%.5g)", v->Num, v->Pos.X,
v->Pos.Y, v->Pos.Z, v->lc);
}
}
else if(c) {
if(permanent){
c->ipar[3] = 2;
}
else{
if(c->beg && c->end)
Msg(STATUS1N, "Curve %d {%d->%d}", c->Num, c->beg->Num, c->end->Num);
else
Msg(STATUS1N, "Curve %d", c->Num);
}
}
else if(s) {
if(permanent){
s->ipar[4] = 2;
}
else{
int nbg = List_Nbr(s->Generatrices);
if(nbg){
sprintf(Message, "Surface %d {", s->Num);
if(nbg < 10) {
for(int i = 0; i < nbg; i++) {
List_Read(s->Generatrices, i, &cc);
if(!i)
sprintf(temp, "%d", cc->Num);
else
sprintf(temp, ",%d", cc->Num);
strcat(Message, temp);
}
}
else {
strcat(Message, "...");
}
strcat(Message, "}");
Msg(STATUS1N, Message);
}
else if (THEM->bds){
BDS_GeomEntity *g = THEM->bds->get_geom ( s->Num, 2);
if (g && g->surf)
Msg(STATUS1N, "Surface %d (%s)", s->Num,g->surf->nameOf().c_str());
else
Msg(STATUS1N, "Surface %d (unknown type)", s->Num);
}
else{
Msg(STATUS1N, "Surface %d", s->Num);
}
}
}
else{
if(!permanent)
Msg(STATUS1N, " ");
}
}
void HighlightEntityNum(int v, int c, int s, int permanent)
{
if(v) {
Vertex *pv = FindPoint(v, THEM);
if(pv)
HighlightEntity(pv, NULL, NULL, permanent);
}
if(c) {
Curve *pc = FindCurve(c, THEM);
if(pc)
HighlightEntity(NULL, pc, NULL, permanent);
}
if(s) {
Surface *ps = FindSurface(s, THEM);
if(ps)
HighlightEntity(NULL, NULL, ps, permanent);
}
}
void ZeroHighlightPoint(void *a, void *b)
{
Vertex *v = *(Vertex **) a;
v->Frozen = 0;
}
void ZeroHighlightCurve(void *a, void *b)
{
Curve *c = *(Curve **) a;
c->ipar[3] = -2;
}
void ZeroHighlightSurface(void *a, void *b)
{
Surface *s = *(Surface **) a;
s->ipar[4] = -2;
}
void ZeroHighlight(Mesh * m)
{
Tree_Action(m->Points, ZeroHighlightPoint);
Tree_Action(m->Curves, ZeroHighlightCurve);
Tree_Action(m->Surfaces, ZeroHighlightSurface);
}
void ZeroHighlightEntityNum(int v, int c, int s)
{
if(v) {
Vertex *pv = FindPoint(v, THEM);
if(pv)
ZeroHighlightPoint(&pv, NULL);
}
if(c) {
Curve *pc = FindCurve(c, THEM);
if(pc)
ZeroHighlightCurve(&pc, NULL);
}
if(s) {
Surface *ps = FindSurface(s, THEM);
if(ps)
ZeroHighlightSurface(&ps, NULL);
}
}