1 // SMESH SMESH : implementaion of SMESH idl descriptions
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : StdMeshers_Quadrangle_2D.cxx
25 // Moved here from SMESH_Quadrangle_2D.cxx
26 // Author : Paul RASCLE, EDF
31 #include "StdMeshers_Quadrangle_2D.hxx"
32 #include "SMESH_Gen.hxx"
33 #include "SMESH_Mesh.hxx"
34 #include "SMESH_subMesh.hxx"
36 #include "SMDS_MeshElement.hxx"
37 #include "SMDS_MeshNode.hxx"
38 #include "SMDS_EdgePosition.hxx"
39 #include "SMDS_FacePosition.hxx"
41 #include <BRep_Tool.hxx>
42 #include <BRepTools.hxx>
43 #include <BRepTools_WireExplorer.hxx>
45 #include <Geom_Surface.hxx>
46 #include <Geom_Curve.hxx>
47 #include <Geom2d_Curve.hxx>
48 #include <GeomAdaptor_Curve.hxx>
49 #include <GCPnts_UniformAbscissa.hxx>
51 #include <Precision.hxx>
52 #include <gp_Pnt2d.hxx>
53 #include <TColStd_ListIteratorOfListOfInteger.hxx>
55 #include "utilities.h"
56 #include "Utils_ExceptHandlers.hxx"
59 //=============================================================================
63 //=============================================================================
65 StdMeshers_Quadrangle_2D::StdMeshers_Quadrangle_2D (int hypId, int studyId, SMESH_Gen* gen)
66 : SMESH_2D_Algo(hypId, studyId, gen)
68 MESSAGE("StdMeshers_Quadrangle_2D::StdMeshers_Quadrangle_2D");
69 _name = "Quadrangle_2D";
70 _shapeType = (1 << TopAbs_FACE);
71 _compatibleHypothesis.push_back("QuadranglePreference");
74 //=============================================================================
78 //=============================================================================
80 StdMeshers_Quadrangle_2D::~StdMeshers_Quadrangle_2D()
82 MESSAGE("StdMeshers_Quadrangle_2D::~StdMeshers_Quadrangle_2D");
85 //=============================================================================
89 //=============================================================================
91 bool StdMeshers_Quadrangle_2D::CheckHypothesis
93 const TopoDS_Shape& aShape,
94 SMESH_Hypothesis::Hypothesis_Status& aStatus)
97 aStatus = SMESH_Hypothesis::HYP_OK;
99 // there is only one compatible Hypothesis so far
100 const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
101 myQuadranglePreference = hyps.size() > 0;
106 //=============================================================================
110 //=============================================================================
112 bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
113 const TopoDS_Shape& aShape) throw (SALOME_Exception)
115 Unexpect aCatch(SalomeException);
116 //MESSAGE("StdMeshers_Quadrangle_2D::Compute");
117 SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
118 aMesh.GetSubMesh(aShape);
120 FaceQuadStruct *quad = CheckAnd2Dcompute(aMesh, aShape);
124 // --- compute 3D values on points, store points & quadrangles
126 int nbdown = quad->nbPts[0];
127 int nbup = quad->nbPts[2];
129 int nbright = quad->nbPts[1];
130 int nbleft = quad->nbPts[3];
132 int nbhoriz = Min(nbdown, nbup);
133 int nbvertic = Min(nbright, nbleft);
135 const TopoDS_Face& F = TopoDS::Face(aShape);
136 Handle(Geom_Surface) S = BRep_Tool::Surface(F);
138 // internal mesh nodes
139 int i, j, geomFaceID = meshDS->ShapeToIndex( F );
140 for (i = 1; i < nbhoriz - 1; i++) {
141 for (j = 1; j < nbvertic - 1; j++) {
142 int ij = j * nbhoriz + i;
143 double u = quad->uv_grid[ij].u;
144 double v = quad->uv_grid[ij].v;
145 gp_Pnt P = S->Value(u, v);
146 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
147 meshDS->SetNodeOnFace(node, geomFaceID, u, v);
148 quad->uv_grid[ij].node = node;
155 // --.--.--.--.--.-- nbvertic
161 // ---.----.----.--- 0
162 // 0 > > > > > > > > nbhoriz
168 int iup = nbhoriz - 1;
169 if (quad->isEdgeOut[3]) { ilow++; } else { if (quad->isEdgeOut[1]) iup--; }
172 int jup = nbvertic - 1;
173 if (quad->isEdgeOut[0]) { jlow++; } else { if (quad->isEdgeOut[2]) jup--; }
175 // regular quadrangles
176 for (i = ilow; i < iup; i++) {
177 for (j = jlow; j < jup; j++) {
178 const SMDS_MeshNode *a, *b, *c, *d;
179 a = quad->uv_grid[j * nbhoriz + i].node;
180 b = quad->uv_grid[j * nbhoriz + i + 1].node;
181 c = quad->uv_grid[(j + 1) * nbhoriz + i + 1].node;
182 d = quad->uv_grid[(j + 1) * nbhoriz + i].node;
183 SMDS_MeshFace * face = meshDS->AddFace(a, b, c, d);
184 meshDS->SetMeshElementOnShape(face, geomFaceID);
188 UVPtStruct *uv_e0 = quad->uv_edges[0];
189 UVPtStruct *uv_e1 = quad->uv_edges[1];
190 UVPtStruct *uv_e2 = quad->uv_edges[2];
191 UVPtStruct *uv_e3 = quad->uv_edges[3];
193 double eps = Precision::Confusion();
195 // Boundary quadrangles
197 if (quad->isEdgeOut[0]) {
200 // |___|___|___|___|___|___|
202 // |___|___|___|___|___|___|
204 // |___|___|___|___|___|___| __ first row of the regular grid
205 // . . . . . . . . . __ down edge nodes
207 // >->->->->->->->->->->->-> -- direction of processing
209 int g = 0; // number of last processed node in the regular grid
211 // number of last node of the down edge to be processed
212 int stop = nbdown - 1;
213 // if right edge is out, we will stop at a node, previous to the last one
214 if (quad->isEdgeOut[1]) stop--;
216 // for each node of the down edge find nearest node
217 // in the first row of the regular grid and link them
218 for (i = 0; i < stop; i++) {
219 const SMDS_MeshNode *a, *b, *c, *d;
221 b = uv_e0[i + 1].node;
222 gp_Pnt pb (b->X(), b->Y(), b->Z());
224 // find node c in the regular grid, which will be linked with node b
227 // right bound reached, link with the rightmost node
229 c = quad->uv_grid[nbhoriz + iup].node;
231 // find in the grid node c, nearest to the b
232 double mind = RealLast();
233 for (int k = g; k <= iup; k++) {
235 const SMDS_MeshNode *nk;
236 if (k < ilow) // this can be, if left edge is out
237 nk = uv_e3[1].node; // get node from the left edge
239 nk = quad->uv_grid[nbhoriz + k].node; // get one of middle nodes
241 gp_Pnt pnk (nk->X(), nk->Y(), nk->Z());
242 double dist = pb.Distance(pnk);
243 if (dist < mind - eps) {
253 if (near == g) { // make triangle
254 SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
255 meshDS->SetMeshElementOnShape(face, geomFaceID);
256 } else { // make quadrangle
260 d = quad->uv_grid[nbhoriz + near - 1].node;
261 SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
262 meshDS->SetMeshElementOnShape(face, geomFaceID);
264 // if node d is not at position g - make additional triangles
266 for (int k = near - 1; k > g; k--) {
267 c = quad->uv_grid[nbhoriz + k].node;
271 d = quad->uv_grid[nbhoriz + k - 1].node;
272 SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
273 meshDS->SetMeshElementOnShape(face, geomFaceID);
280 if (quad->isEdgeOut[2]) {
283 // <-<-<-<-<-<-<-<-<-<-<-<-< -- direction of processing
285 // . . . . . . . . . __ up edge nodes
286 // ___ ___ ___ ___ ___ ___ __ first row of the regular grid
288 // |___|___|___|___|___|___|
290 // |___|___|___|___|___|___|
293 int g = nbhoriz - 1; // last processed node in the regular grid
296 // if left edge is out, we will stop at a second node
297 if (quad->isEdgeOut[3]) stop++;
299 // for each node of the up edge find nearest node
300 // in the first row of the regular grid and link them
301 for (i = nbup - 1; i > stop; i--) {
302 const SMDS_MeshNode *a, *b, *c, *d;
304 b = uv_e2[i - 1].node;
305 gp_Pnt pb (b->X(), b->Y(), b->Z());
307 // find node c in the grid, which will be linked with node b
309 if (i == stop + 1) { // left bound reached, link with the leftmost node
310 c = quad->uv_grid[nbhoriz*(nbvertic - 2) + ilow].node;
313 // find node c in the grid, nearest to the b
314 double mind = RealLast();
315 for (int k = g; k >= ilow; k--) {
316 const SMDS_MeshNode *nk;
318 nk = uv_e1[nbright - 2].node;
320 nk = quad->uv_grid[nbhoriz*(nbvertic - 2) + k].node;
321 gp_Pnt pnk (nk->X(), nk->Y(), nk->Z());
322 double dist = pb.Distance(pnk);
323 if (dist < mind - eps) {
333 if (near == g) { // make triangle
334 SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
335 meshDS->SetMeshElementOnShape(face, geomFaceID);
336 } else { // make quadrangle
338 d = uv_e1[nbright - 2].node;
340 d = quad->uv_grid[nbhoriz*(nbvertic - 2) + near + 1].node;
341 SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
342 meshDS->SetMeshElementOnShape(face, geomFaceID);
344 if (near + 1 < g) { // if d not is at g - make additional triangles
345 for (int k = near + 1; k < g; k++) {
346 c = quad->uv_grid[nbhoriz*(nbvertic - 2) + k].node;
348 d = uv_e1[nbright - 2].node;
350 d = quad->uv_grid[nbhoriz*(nbvertic - 2) + k + 1].node;
351 SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
352 meshDS->SetMeshElementOnShape(face, geomFaceID);
361 // right or left boundary quadrangles
362 if (quad->isEdgeOut[1]) {
363 // MESSAGE("right edge is out");
364 int g = 0; // last processed node in the grid
365 int stop = nbright - 1;
366 if (quad->isEdgeOut[2]) stop--;
367 for (i = 0; i < stop; i++) {
368 const SMDS_MeshNode *a, *b, *c, *d;
370 b = uv_e1[i + 1].node;
371 gp_Pnt pb (b->X(), b->Y(), b->Z());
373 // find node c in the grid, nearest to the b
375 if (i == stop - 1) { // up bondary reached
376 c = quad->uv_grid[nbhoriz*(jup + 1) - 2].node;
379 double mind = RealLast();
380 for (int k = g; k <= jup; k++) {
381 const SMDS_MeshNode *nk;
383 nk = uv_e0[nbdown - 2].node;
385 nk = quad->uv_grid[nbhoriz*(k + 1) - 2].node;
386 gp_Pnt pnk (nk->X(), nk->Y(), nk->Z());
387 double dist = pb.Distance(pnk);
388 if (dist < mind - eps) {
398 if (near == g) { // make triangle
399 SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
400 meshDS->SetMeshElementOnShape(face, geomFaceID);
401 } else { // make quadrangle
403 d = uv_e0[nbdown - 2].node;
405 d = quad->uv_grid[nbhoriz*near - 2].node;
406 SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
407 meshDS->SetMeshElementOnShape(face, geomFaceID);
409 if (near - 1 > g) { // if d not is at g - make additional triangles
410 for (int k = near - 1; k > g; k--) {
411 c = quad->uv_grid[nbhoriz*(k + 1) - 2].node;
413 d = uv_e0[nbdown - 2].node;
415 d = quad->uv_grid[nbhoriz*k - 2].node;
416 SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
417 meshDS->SetMeshElementOnShape(face, geomFaceID);
424 if (quad->isEdgeOut[3]) {
425 // MESSAGE("left edge is out");
426 int g = nbvertic - 1; // last processed node in the grid
428 if (quad->isEdgeOut[0]) stop++;
429 for (i = nbleft - 1; i > stop; i--) {
430 const SMDS_MeshNode *a, *b, *c, *d;
432 b = uv_e3[i - 1].node;
433 gp_Pnt pb (b->X(), b->Y(), b->Z());
435 // find node c in the grid, nearest to the b
437 if (i == stop + 1) { // down bondary reached
438 c = quad->uv_grid[nbhoriz*jlow + 1].node;
441 double mind = RealLast();
442 for (int k = g; k >= jlow; k--) {
443 const SMDS_MeshNode *nk;
447 nk = quad->uv_grid[nbhoriz*k + 1].node;
448 gp_Pnt pnk (nk->X(), nk->Y(), nk->Z());
449 double dist = pb.Distance(pnk);
450 if (dist < mind - eps) {
460 if (near == g) { // make triangle
461 SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
462 meshDS->SetMeshElementOnShape(face, geomFaceID);
463 } else { // make quadrangle
467 d = quad->uv_grid[nbhoriz*(near + 1) + 1].node;
468 SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
469 meshDS->SetMeshElementOnShape(face, geomFaceID);
471 if (near + 1 < g) { // if d not is at g - make additional triangles
472 for (int k = near + 1; k < g; k++) {
473 c = quad->uv_grid[nbhoriz*k + 1].node;
477 d = quad->uv_grid[nbhoriz*(k + 1) + 1].node;
478 SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
479 meshDS->SetMeshElementOnShape(face, geomFaceID);
493 //=============================================================================
497 //=============================================================================
499 FaceQuadStruct *StdMeshers_Quadrangle_2D::CheckAnd2Dcompute
500 (SMESH_Mesh & aMesh, const TopoDS_Shape & aShape) throw(SALOME_Exception)
502 Unexpect aCatch(SalomeException);
504 const TopoDS_Face & F = TopoDS::Face(aShape);
506 // verify 1 wire only, with 4 edges
508 if (NumberOfWires(F) != 1)
510 INFOS("only 1 wire by face (quadrangles)");
513 const TopoDS_Wire& W = BRepTools::OuterWire(F);
514 BRepTools_WireExplorer wexp (W, F);
516 FaceQuadStruct *quad = new FaceQuadStruct;
517 for (int i = 0; i < 4; i++)
518 quad->uv_edges[i] = 0;
522 for (wexp.Init(W, F); wexp.More(); wexp.Next())
524 const TopoDS_Edge& E = wexp.Current();
525 int nb = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
528 quad->edge[nbEdges] = E;
529 quad->nbPts[nbEdges] = nb + 2; // internal points + 2 extrema
536 INFOS("face must have 4 edges /quadrangles");
541 // set normalized grid on unit square in parametric domain
543 SetNormalizedGrid(aMesh, F, quad);
548 //=============================================================================
552 //=============================================================================
554 void StdMeshers_Quadrangle_2D::QuadDelete (FaceQuadStruct * quad)
556 //MESSAGE("StdMeshers_Quadrangle_2D::QuadDelete");
559 for (int i = 0; i < 4; i++)
561 if (quad->uv_edges[i])
562 delete [] quad->uv_edges[i];
563 quad->edge[i].Nullify();
566 delete [] quad->uv_grid;
571 //=============================================================================
575 //=============================================================================
577 void StdMeshers_Quadrangle_2D::SetNormalizedGrid (SMESH_Mesh & aMesh,
578 const TopoDS_Shape& aShape,
579 FaceQuadStruct* quad) throw (SALOME_Exception)
581 Unexpect aCatch(SalomeException);
582 // Algorithme décrit dans "Génération automatique de maillages"
583 // P.L. GEORGE, MASSON, § 6.4.1 p. 84-85
584 // traitement dans le domaine paramétrique 2d u,v
585 // transport - projection sur le carré unité
587 // MESSAGE("StdMeshers_Quadrangle_2D::SetNormalizedGrid");
588 const TopoDS_Face& F = TopoDS::Face(aShape);
590 // 1 --- find orientation of the 4 edges, by test on extrema
593 // |<----north-2-------^ a3 -------------> a2
595 // west-3 east-1 =right | |
599 // v----south-0--------> a0 -------------> a1
604 Handle(Geom2d_Curve) c2d[4];
607 for (int i = 0; i < 4; i++)
609 c2d[i] = BRep_Tool::CurveOnSurface(quad->edge[i], F,
610 quad->first[i], quad->last[i]);
611 pf[i] = c2d[i]->Value(quad->first[i]);
612 pl[i] = c2d[i]->Value(quad->last[i]);
613 quad->isEdgeForward[i] = false;
616 double l0f1 = pl[0].SquareDistance(pf[1]);
617 double l0l1 = pl[0].SquareDistance(pl[1]);
618 double f0f1 = pf[0].SquareDistance(pf[1]);
619 double f0l1 = pf[0].SquareDistance(pl[1]);
620 if ( Min( l0f1, l0l1 ) < Min ( f0f1, f0l1 ))
622 quad->isEdgeForward[0] = true;
624 double tmp = quad->first[0];
625 quad->first[0] = quad->last[0];
627 pf[0] = c2d[0]->Value(quad->first[0]);
628 pl[0] = c2d[0]->Value(quad->last[0]);
630 for (int i = 1; i < 4; i++)
632 l0l1 = pl[i - 1].SquareDistance(pl[i]);
633 l0f1 = pl[i - 1].SquareDistance(pf[i]);
634 quad->isEdgeForward[i] = ( l0f1 < l0l1 );
635 if (!quad->isEdgeForward[i])
637 double tmp = quad->first[i];
638 quad->first[i] = quad->last[i];
640 pf[i] = c2d[i]->Value(quad->first[i]);
641 pl[i] = c2d[i]->Value(quad->last[i]);
645 // 2 --- load 2d edge points (u,v) with orientation and value on unit square
648 for (int i = 0; i < 2; i++)
650 quad->uv_edges[i] = LoadEdgePoints(aMesh, F, quad->edge[i],
651 quad->first[i], quad->last[i]);
652 if (!quad->uv_edges[i]) loadOk = false;
655 for (int i = 2; i < 4; i++)
657 quad->uv_edges[i] = LoadEdgePoints(aMesh, F, quad->edge[i],
658 quad->last[i], quad->first[i]);
659 if (!quad->uv_edges[i]) loadOk = false;
664 INFOS("StdMeshers_Quadrangle_2D::SetNormalizedGrid - LoadEdgePoints failed");
669 // 3 --- 2D normalized values on unit square [0..1][0..1]
671 int nbhoriz = Min(quad->nbPts[0], quad->nbPts[2]);
672 int nbvertic = Min(quad->nbPts[1], quad->nbPts[3]);
674 quad->isEdgeOut[0] = (quad->nbPts[0] > quad->nbPts[2]);
675 quad->isEdgeOut[1] = (quad->nbPts[1] > quad->nbPts[3]);
676 quad->isEdgeOut[2] = (quad->nbPts[2] > quad->nbPts[0]);
677 quad->isEdgeOut[3] = (quad->nbPts[3] > quad->nbPts[1]);
679 quad->uv_grid = new UVPtStruct[nbvertic * nbhoriz];
681 UVPtStruct *uv_grid = quad->uv_grid;
682 UVPtStruct *uv_e0 = quad->uv_edges[0];
683 UVPtStruct *uv_e1 = quad->uv_edges[1];
684 UVPtStruct *uv_e2 = quad->uv_edges[2];
685 UVPtStruct *uv_e3 = quad->uv_edges[3];
687 // nodes Id on "in" edges
688 if (! quad->isEdgeOut[0]) {
690 for (int i = 0; i < nbhoriz; i++) { // down
691 int ij = j * nbhoriz + i;
692 uv_grid[ij].node = uv_e0[i].node;
695 if (! quad->isEdgeOut[1]) {
697 for (int j = 0; j < nbvertic; j++) { // right
698 int ij = j * nbhoriz + i;
699 uv_grid[ij].node = uv_e1[j].node;
702 if (! quad->isEdgeOut[2]) {
703 int j = nbvertic - 1;
704 for (int i = 0; i < nbhoriz; i++) { // up
705 int ij = j * nbhoriz + i;
706 uv_grid[ij].node = uv_e2[i].node;
709 if (! quad->isEdgeOut[3]) {
711 for (int j = 0; j < nbvertic; j++) { // left
712 int ij = j * nbhoriz + i;
713 uv_grid[ij].node = uv_e3[j].node;
717 // falsificate "out" edges
718 if (quad->isEdgeOut[0]) // down
719 uv_e0 = MakeEdgePoints
720 (aMesh, F, quad->edge[0], quad->first[0], quad->last[0], nbhoriz - 1);
721 else if (quad->isEdgeOut[2]) // up
722 uv_e2 = MakeEdgePoints
723 (aMesh, F, quad->edge[2], quad->last[2], quad->first[2], nbhoriz - 1);
725 if (quad->isEdgeOut[1]) // right
726 uv_e1 = MakeEdgePoints
727 (aMesh, F, quad->edge[1], quad->first[1], quad->last[1], nbvertic - 1);
728 else if (quad->isEdgeOut[3]) // left
729 uv_e3 = MakeEdgePoints
730 (aMesh, F, quad->edge[3], quad->last[3], quad->first[3], nbvertic - 1);
732 // normalized 2d values on grid
733 for (int i = 0; i < nbhoriz; i++)
735 for (int j = 0; j < nbvertic; j++)
737 int ij = j * nbhoriz + i;
738 // --- droite i cste : x = x0 + y(x1-x0)
739 double x0 = uv_e0[i].normParam; // bas - sud
740 double x1 = uv_e2[i].normParam; // haut - nord
741 // --- droite j cste : y = y0 + x(y1-y0)
742 double y0 = uv_e3[j].normParam; // gauche-ouest
743 double y1 = uv_e1[j].normParam; // droite - est
744 // --- intersection : x=x0+(y0+x(y1-y0))(x1-x0)
745 double x = (x0 + y0 * (x1 - x0)) / (1 - (y1 - y0) * (x1 - x0));
746 double y = y0 + x * (y1 - y0);
749 //MESSAGE("-xy-01 "<<x0<<" "<<x1<<" "<<y0<<" "<<y1);
750 //MESSAGE("-xy-norm "<<i<<" "<<j<<" "<<x<<" "<<y);
754 // 4 --- projection on 2d domain (u,v)
760 for (int i = 0; i < nbhoriz; i++)
762 for (int j = 0; j < nbvertic; j++)
764 int ij = j * nbhoriz + i;
765 double x = uv_grid[ij].x;
766 double y = uv_grid[ij].y;
767 double param_0 = uv_e0[0].param + x * (uv_e0[nbhoriz - 1].param - uv_e0[0].param); // sud
768 double param_2 = uv_e2[0].param + x * (uv_e2[nbhoriz - 1].param - uv_e2[0].param); // nord
769 double param_1 = uv_e1[0].param + y * (uv_e1[nbvertic - 1].param - uv_e1[0].param); // est
770 double param_3 = uv_e3[0].param + y * (uv_e3[nbvertic - 1].param - uv_e3[0].param); // ouest
772 //MESSAGE("params "<<param_0<<" "<<param_1<<" "<<param_2<<" "<<param_3);
773 gp_Pnt2d p0 = c2d[0]->Value(param_0);
774 gp_Pnt2d p1 = c2d[1]->Value(param_1);
775 gp_Pnt2d p2 = c2d[2]->Value(param_2);
776 gp_Pnt2d p3 = c2d[3]->Value(param_3);
778 double u = (1 - y) * p0.X() + x * p1.X() + y * p2.X() + (1 - x) * p3.X();
779 double v = (1 - y) * p0.Y() + x * p1.Y() + y * p2.Y() + (1 - x) * p3.Y();
781 u -= (1 - x) * (1 - y) * a0.X() + x * (1 - y) * a1.X() +
782 x * y * a2.X() + (1 - x) * y * a3.X();
783 v -= (1 - x) * (1 - y) * a0.Y() + x * (1 - y) * a1.Y() +
784 x * y * a2.Y() + (1 - x) * y * a3.Y();
792 //=============================================================================
796 //=============================================================================
797 UVPtStruct* StdMeshers_Quadrangle_2D::LoadEdgePoints (SMESH_Mesh & aMesh,
798 const TopoDS_Face& F,
799 const TopoDS_Edge& E,
800 double first, double last)
803 //MESSAGE("StdMeshers_Quadrangle_2D::LoadEdgePoints");
805 // --- IDNodes of first and last Vertex
807 TopoDS_Vertex VFirst, VLast;
808 TopExp::Vertices(E, VFirst, VLast); // corresponds to f and l
810 ASSERT(!VFirst.IsNull());
811 SMDS_NodeIteratorPtr lid = aMesh.GetSubMesh(VFirst)->GetSubMeshDS()->GetNodes();
814 MESSAGE ( "NO NODE BUILT ON VERTEX" );
817 const SMDS_MeshNode* idFirst = lid->next();
819 ASSERT(!VLast.IsNull());
820 lid = aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes();
823 MESSAGE ( "NO NODE BUILT ON VERTEX" );
826 const SMDS_MeshNode* idLast = lid->next();
828 // --- edge internal IDNodes (relies on good order storage, not checked)
830 map<double, const SMDS_MeshNode *> params;
831 SMDS_NodeIteratorPtr ite = aMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes();
835 const SMDS_MeshNode* node = ite->next();
836 const SMDS_EdgePosition* epos =
837 static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
838 double param = epos->GetUParameter();
839 params[param] = node;
842 int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
843 if (nbPoints != params.size())
845 MESSAGE( "BAD NODE ON EDGE POSITIONS" );
848 UVPtStruct* uvslf = new UVPtStruct[nbPoints + 2];
851 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
853 bool isForward = (((l - f) * (last - first)) > 0);
860 gp_Pnt2d p = C2d->Value(f); // first point = Vertex Forward
864 uvslf[0].node = idFirst;
865 //MESSAGE("__ f "<<f<<" "<<uvslf[0].x <<" "<<uvslf[0].y);
866 map < double, const SMDS_MeshNode* >::iterator itp = params.begin();
867 for (int i = 1; i <= nbPoints; i++) // nbPoints internal
869 double param = (*itp).first;
870 gp_Pnt2d p = C2d->Value(param);
873 uvslf[i].param = param;
874 uvslf[i].node = (*itp).second;
875 //MESSAGE("__ "<<i<<" "<<param<<" "<<uvslf[i].x <<" "<<uvslf[i].y);
878 p = C2d->Value(l); // last point = Vertex Reversed
879 uvslf[nbPoints + 1].x = p.X();
880 uvslf[nbPoints + 1].y = p.Y();
881 uvslf[nbPoints + 1].param = l;
882 uvslf[nbPoints + 1].node = idLast;
883 //MESSAGE("__ l "<<l<<" "<<uvslf[nbPoints+1].x <<" "<<uvslf[nbPoints+1].y);
888 gp_Pnt2d p = C2d->Value(l); // first point = Vertex Reversed
892 uvslf[0].node = idLast;
893 //MESSAGE("__ l "<<l<<" "<<uvslf[0].x <<" "<<uvslf[0].y);
894 map < double, const SMDS_MeshNode* >::reverse_iterator itp = params.rbegin();
896 for (int j = nbPoints; j >= 1; j--) // nbPoints internal
898 double param = (*itp).first;
899 int i = nbPoints + 1 - j;
900 gp_Pnt2d p = C2d->Value(param);
903 uvslf[i].param = param;
904 uvslf[i].node = (*itp).second;
905 //MESSAGE("__ "<<i<<" "<<param<<" "<<uvslf[i].x <<" "<<uvslf[i].y);
908 p = C2d->Value(f); // last point = Vertex Forward
909 uvslf[nbPoints + 1].x = p.X();
910 uvslf[nbPoints + 1].y = p.Y();
911 uvslf[nbPoints + 1].param = f;
912 uvslf[nbPoints + 1].node = idFirst;
913 //MESSAGE("__ f "<<f<<" "<<uvslf[nbPoints+1].x <<" "<<uvslf[nbPoints+1].y);
916 ASSERT(paramin != paramax);
917 for (int i = 0; i < nbPoints + 2; i++)
919 uvslf[i].normParam = (uvslf[i].param - paramin) / (paramax - paramin);
925 //=============================================================================
929 //=============================================================================
930 UVPtStruct* StdMeshers_Quadrangle_2D::MakeEdgePoints (SMESH_Mesh & aMesh,
931 const TopoDS_Face& F,
932 const TopoDS_Edge& E,
933 double first, double last,
936 // MESSAGE("StdMeshers_Quadrangle_2D::MakeEdgePoints");
938 UVPtStruct* uvslf = new UVPtStruct[nb_segm + 1];
941 // --- edge internal points
943 Handle(Geom_Curve) Curve = BRep_Tool::Curve(E, fi, li);
944 if (!Curve.IsNull()) {
946 GeomAdaptor_Curve C3d (Curve);
947 double length = EdgeLength(E);
948 double eltSize = length / nb_segm;
949 GCPnts_UniformAbscissa Discret (C3d, eltSize, fi, li);
950 if (!Discret.IsDone()) return false;
951 int NbPoints = Discret.NbPoints();
952 for (int i = 1; i <= NbPoints; i++) {
953 double param = Discret.Parameter(i);
954 params.push_back(param);
957 catch (Standard_Failure) {
963 // Edge is a degenerated Edge
964 BRep_Tool::Range(E, fi, li);
965 double du = (li - fi) / nb_segm;
966 for (int i = 1; i <= nb_segm + 1; i++)
968 double param = fi + (i - 1) * du;
969 params.push_back(param);
974 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
977 bool isForward = (((l - f) * (last - first)) > 0);
979 list<double>::iterator itU = params.begin();
980 for (int i = 0; i <= nb_segm; i++) // nbPoints internal
983 gp_Pnt2d p = C2d->Value(param);
986 uvslf[i].param = param;
987 uvslf[i].normParam = (param - f) / (l - f);
991 list<double>::reverse_iterator itU = params.rbegin();
992 for (int j = nb_segm; j >= 0; j--) // nbPoints internal
996 gp_Pnt2d p = C2d->Value(param);
999 uvslf[i].param = param;
1000 uvslf[i].normParam = (param - l) / (f - l);
1009 //=============================================================================
1013 //=============================================================================
1015 ostream & StdMeshers_Quadrangle_2D::SaveTo(ostream & save)
1020 //=============================================================================
1024 //=============================================================================
1026 istream & StdMeshers_Quadrangle_2D::LoadFrom(istream & load)
1031 //=============================================================================
1035 //=============================================================================
1037 ostream & operator <<(ostream & save, StdMeshers_Quadrangle_2D & hyp)
1039 return hyp.SaveTo( save );
1042 //=============================================================================
1046 //=============================================================================
1048 istream & operator >>(istream & load, StdMeshers_Quadrangle_2D & hyp)
1050 return hyp.LoadFrom( load );