Forked from
gmsh / gmsh
16993 commits behind the upstream repository.
-
Christophe Geuzaine authoredChristophe Geuzaine authored
gmshEdge.cpp 8.29 KiB
// $Id: gmshEdge.cpp,v 1.37 2007-08-29 14:18:25 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>.
#include "GFace.h"
#include "gmshEdge.h"
#include "Geo.h"
#include "GeoInterpolation.h"
#include "Message.h"
#include "Context.h"
extern Context_T CTX;
extern Mesh *THEM;
gmshEdge::gmshEdge(GModel *model, Curve *edge, GVertex *v1, GVertex *v2)
: GEdge(model, edge->Num, v1, v2), c(edge)
{
resetMeshAttributes();
}
gmshEdge::gmshEdge(GModel *model, int num)
: GEdge(model, num, 0, 0)
{
c = Create_Curve(num, MSH_SEGM_DISCRETE, 0, NULL, NULL, -1, -1, 0., 1.);
Tree_Add(THEM->Curves, &c);
CreateReversedCurve(c);
}
void gmshEdge::resetMeshAttributes()
{
meshAttributes.Method = c->Method;
meshAttributes.nbPointsTransfinite = c->ipar[0];
meshAttributes.coeffTransfinite = c->dpar[0];
meshAttributes.typeTransfinite = c->ipar[1];
meshAttributes.extrude = c->Extrude;
}
Range<double> gmshEdge::parBounds(int i) const
{
return(Range<double>(c->ubeg, c->uend));
}
GPoint gmshEdge::point(double par) const
{
Vertex a = InterpolateCurve(c, par, 0);
return GPoint(a.Pos.X,a.Pos.Y,a.Pos.Z,this,par);
}
GPoint gmshEdge::closestPoint(const SPoint3 & qp)
{
Vertex v;
Vertex a;
Vertex der;
v.Pos.X = qp.x();
v.Pos.Y = qp.y();
v.Pos.Z = qp.z();
ProjectPointOnCurve(c, &v, &a, &der);
return GPoint(a.Pos.X, a.Pos.Y, a.Pos.Z, this, a.u);
}
int gmshEdge::containsParam(double pt) const
{
Range<double> rg = parBounds(0);
return (pt >= rg.low() && pt <= rg.high());
}
SVector3 gmshEdge::firstDer(double par) const
{
Vertex a = InterpolateCurve(c, par, 1);
return SVector3(a.Pos.X, a.Pos.Y, a.Pos.Z);
}
double gmshEdge::parFromPoint(const SPoint3 &pt) const
{
Vertex v;
Vertex a;
Vertex der;
v.Pos.X = pt.x();
v.Pos.Y = pt.y();
v.Pos.Z = pt.z();
ProjectPointOnCurve(c, &v, &a, &der);
return a.u;
}
GEntity::GeomType gmshEdge::geomType() const
{
switch (c->Typ){
case MSH_SEGM_LINE : return Line;
case MSH_SEGM_PARAMETRIC : return ParametricCurve;
case MSH_SEGM_CIRC :
case MSH_SEGM_CIRC_INV : return Circle;
case MSH_SEGM_ELLI:
case MSH_SEGM_ELLI_INV: return Ellipse;
case MSH_SEGM_BSPLN:
case MSH_SEGM_BEZIER:
case MSH_SEGM_NURBS:
case MSH_SEGM_SPLN: return Nurb;
case MSH_SEGM_BND_LAYER: return BoundaryLayerCurve;
case MSH_SEGM_DISCRETE: return DiscreteCurve;
default : return Unknown;
}
}
int gmshEdge::minimumMeshSegments () const
{
if(geomType() == Circle || geomType() == Ellipse)
return (int)(fabs(c->Circle.t1 - c->Circle.t2) *
(double)CTX.mesh.min_circ_points / Pi) - 1;
else
return GEdge::minimumMeshSegments () ;
}
int gmshEdge::minimumDrawSegments () const
{
int n = List_Nbr(c->Control_Points) - 1;
if(!n) n = GEdge::minimumDrawSegments();
if(geomType() == Line && ! c->geometry)
return n;
else if(geomType() == Circle || geomType() == Ellipse)
return CTX.geom.circle_points;
else
return 10 * n;
}
SPoint2 gmshEdge::reparamOnFace(GFace *face, double epar,int dir) const
{
Surface *s = (Surface*) face->getNativePtr();
bool periodic = (c->end == c->beg);
if(s->geometry){
switch (c->Typ) {
case MSH_SEGM_LINE:
{
Vertex *v[3];
List_Read(c->Control_Points, 0, &v[1]);
List_Read(c->Control_Points, 1, &v[2]);
SPoint2 p = v[1]->pntOnGeometry +
(v[2]->pntOnGeometry - v[1]->pntOnGeometry) * epar;
return p;
}
case MSH_SEGM_BSPLN:
case MSH_SEGM_BEZIER:
{
int NbControlPoints = List_Nbr(c->Control_Points);
int NbCurves = NbControlPoints + (periodic ? -1 : 1);
int iCurve = (int)floor(epar * (double)NbCurves);
if(iCurve >= NbCurves)
iCurve = NbCurves - 1;
else if (iCurve < 0) // ? does it happen ?
iCurve = 0;
double t1 = (double)(iCurve) / (double)(NbCurves);
double t2 = (double)(iCurve+1) / (double)(NbCurves);
double t = (epar - t1) / (t2 - t1);
Vertex *v[4];
for(int j = 0; j < 4; j ++ ){
int k = iCurve - (periodic ? 1 : 2) + j;
if(k < 0)
k = periodic ? k + NbControlPoints - 1 : 0;
if(k >= NbControlPoints)
k = periodic ? k - NbControlPoints + 1: NbControlPoints - 1;
List_Read(c->Control_Points, k, &v[j]);
}
return InterpolateCubicSpline(v, t, c->mat, 0, t1, t2, c->geometry);
}
case MSH_SEGM_SPLN :
{
Vertex temp1, temp2;
int N = List_Nbr(c->Control_Points);
int i = (int)((double)(N - 1) * epar);
if(i < 0)
i = 0;
if(i >= N - 1)
i = N - 2;
double t1 = (double)(i) / (double)(N - 1);
double t2 = (double)(i + 1) / (double)(N - 1);
double t = (epar - t1) / (t2 - t1);
Vertex *v[4];
List_Read(c->Control_Points, i, &v[1]);
List_Read(c->Control_Points, i + 1, &v[2]);
if(!i) {
if(c->beg == c->end){
List_Read(c->Control_Points,N-2,&v[0]);
}
else{
v[0] = &temp1;
v[0]->pntOnGeometry = v[1]->pntOnGeometry * 2. - v[2]->pntOnGeometry;
}
}
else{
List_Read(c->Control_Points, i - 1, &v[0]);
}
if(i == N - 2) {
if(c->beg == c->end){
List_Read(c->Control_Points,1,&v[3]);
}
else{
v[3] = &temp2;
v[3]->pntOnGeometry = v[2]->pntOnGeometry * 2. - v[1]->pntOnGeometry;
}
}
else{
List_Read(c->Control_Points, i + 2, &v[3]);
}
return InterpolateCubicSpline(v, t, c->mat, 0, t1, t2, c->geometry);
}
default:
throw;
}
}
if(s->Typ == MSH_SURF_REGL){
Curve *C[4];
for(int i = 0; i < 4; i++)
List_Read(s->Generatrices, i, &C[i]);
double U, V;
if (C[0]->Num == c->Num) {
U = (epar - C[0]->ubeg) / (C[0]->uend - C[0]->ubeg) ;
V = 0;
}
else if (C[0]->Num == -c->Num) {
U = (C[0]->uend - epar - C[0]->ubeg) / (C[0]->uend - C[0]->ubeg) ;
V = 0;
}
else if (C[1]->Num == c->Num) {
V = (epar - C[1]->ubeg) / (C[1]->uend - C[1]->ubeg) ;
U = 1;
}
else if (C[1]->Num == -c->Num) {
V = (C[1]->uend - epar - C[1]->ubeg) / (C[1]->uend - C[1]->ubeg) ;
U = 1;
}
else if (C[2]->Num == c->Num) {
U = 1 - (epar - C[2]->ubeg) / (C[2]->uend - C[2]->ubeg) ;
V = 1;
}
else if (C[2]->Num == -c->Num) {
U = 1 - ( C[2]->uend -epar - C[2]->ubeg) / (C[2]->uend - C[2]->ubeg) ;
V = 1;
}
else if (C[3]->Num == c->Num) {
V = 1-(epar - C[3]->ubeg) / (C[3]->uend - C[3]->ubeg) ;
U = 0;
}
else if (C[3]->Num == -c->Num) {
V = 1-(C[3]->uend - epar - C[3]->ubeg) / (C[3]->uend - C[3]->ubeg) ;
U = 0;
}
else{
Msg(INFO, "Reparameterizing edge %d on face %d", c->Num, s->Num);
return GEdge::reparamOnFace(face, epar, dir);
}
return SPoint2(U, V);
}
else if (s->Typ == MSH_SURF_TRIC){
Curve *C[3];
for(int i = 0; i < 3; i++)
List_Read(s->Generatrices, i, &C[i]);
double U, V;
if (C[0]->Num == c->Num) {
U = (epar - C[0]->ubeg) / (C[0]->uend - C[0]->ubeg) ;
V = 0;
}
else if (C[0]->Num == -c->Num) {
U = (C[0]->uend - epar - C[0]->ubeg) / (C[0]->uend - C[0]->ubeg) ;
V = 0;
}
else if (C[1]->Num == c->Num) {
V = (epar - C[1]->ubeg) / (C[1]->uend - C[1]->ubeg) ;
U = 1;
}
else if (C[1]->Num == -c->Num) {
V = (C[1]->uend - epar - C[1]->ubeg) / (C[1]->uend - C[1]->ubeg) ;
U = 1;
}
else if (C[2]->Num == c->Num) {
U = 1-(epar - C[2]->ubeg) / (C[2]->uend - C[2]->ubeg) ;
V = 1;
}
else if (C[2]->Num == -c->Num) {
U = 1-(C[2]->uend - epar - C[2]->ubeg) / (C[2]->uend - C[2]->ubeg) ;
V = 1;
}
else{
Msg(INFO, "Reparameterizing edge %d on face %d", c->Num, s->Num);
return GEdge::reparamOnFace(face, epar, dir);
}
return SPoint2(U, V);
}
else
return GEdge::reparamOnFace(face, epar, dir);
}