- //MESSAGE("StdMeshers_Quadrangle_2D::Compute");
- SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
- SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape);
-
- FaceQuadStruct *quad = CheckAnd2Dcompute(aMesh, aShape);
- if (!quad)
- return false;
-
- // --- compute 3D values on points, store points & quadrangles
-
- int nbdown = quad->nbPts[0];
- int nbright = quad->nbPts[1];
- int nbVertices = nbdown * nbright;
- int nbQuad = (nbdown - 1) * (nbright - 1);
- //SCRUTE(nbVertices);
- //SCRUTE(nbQuad);
-
- // const TopoDS_Face& FF = TopoDS::Face(aShape);
- // bool faceIsForward = (FF.Orientation() == TopAbs_FORWARD);
- // TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD));
- const TopoDS_Face & F = TopoDS::Face(aShape);
- bool faceIsForward = (F.Orientation() == TopAbs_FORWARD);
- Handle(Geom_Surface) S = BRep_Tool::Surface(F);
-
- for (int i = 1; i < nbdown - 1; i++)
- for (int j = 1; j < nbright - 1; j++) // internal points
- {
- int ij = j * nbdown + i;
- double u = quad->uv_grid[ij].u;
- double v = quad->uv_grid[ij].v;
- gp_Pnt P = S->Value(u, v);
- SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
- meshDS->SetNodeOnFace(node, F);
- quad->uv_grid[ij].node = node;
-// Handle (SMDS_FacePosition) fpos
-// = new SMDS_FacePosition(theSubMesh->GetId(),i,j); // easier than u,v
-// node->SetPosition(fpos);
- SMDS_FacePosition* fpos =
- dynamic_cast<SMDS_FacePosition*>(node->GetPosition().get());
- fpos->SetUParameter(i);
- fpos->SetVParameter(j);
- }
-
- // bool isQuadForward = ( faceIsForward == quad->isEdgeForward[0]);
- for (int i = 0; i < nbdown - 1; i++)
- for (int j = 0; j < nbright - 1; j++) // faces
- {
- const SMDS_MeshNode *a, *b, *c, *d;
- a = quad->uv_grid[j * nbdown + i].node;
- b = quad->uv_grid[j * nbdown + i + 1].node;
- c = quad->uv_grid[(j + 1) * nbdown + i + 1].node;
- d = quad->uv_grid[(j + 1) * nbdown + i].node;
- // if (isQuadForward) faceId = meshDS->AddFace(a,b,c,d);
- // else faceId = meshDS->AddFace(a,d,c,b);
- SMDS_MeshFace * face = meshDS->AddFace(a, b, c, d);
- meshDS->SetMeshElementOnShape(face, F);
- }
-
- QuadDelete(quad);
- bool isOk = true;
- return isOk;
+ //MESSAGE("StdMeshers_Quadrangle_2D::Compute");
+ SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
+ aMesh.GetSubMesh(aShape);
+
+ FaceQuadStruct *quad = CheckAnd2Dcompute(aMesh, aShape);
+ if (!quad)
+ return false;
+
+ // --- compute 3D values on points, store points & quadrangles
+
+ int nbdown = quad->nbPts[0];
+ int nbup = quad->nbPts[2];
+// bool isDownOut = (nbdown > nbup);
+// bool isUpOut = (nbdown < nbup);
+
+ int nbright = quad->nbPts[1];
+ int nbleft = quad->nbPts[3];
+// bool isRightOut = (nbright > nbleft);
+// bool isLeftOut = (nbright < nbleft);
+
+ int nbhoriz = Min(nbdown, nbup);
+ int nbvertic = Min(nbright, nbleft);
+
+ const TopoDS_Face& F = TopoDS::Face(aShape);
+ Handle(Geom_Surface) S = BRep_Tool::Surface(F);
+
+ // internal mesh nodes
+ int i, j;
+ for (i = 1; i < nbhoriz - 1; i++) {
+ for (j = 1; j < nbvertic - 1; j++) {
+ int ij = j * nbhoriz + i;
+ double u = quad->uv_grid[ij].u;
+ double v = quad->uv_grid[ij].v;
+ gp_Pnt P = S->Value(u, v);
+ SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
+ meshDS->SetNodeOnFace(node, F);
+ quad->uv_grid[ij].node = node;
+ SMDS_FacePosition* fpos =
+ dynamic_cast<SMDS_FacePosition*>(node->GetPosition().get());
+ fpos->SetUParameter(u);
+ fpos->SetVParameter(v);
+ }
+ }
+
+ // mesh faces
+
+ // [2]
+ // --.--.--.--.--.-- nbvertic
+ // | | ^
+ // | | ^
+ // [3] | | ^ j [1]
+ // | | ^
+ // | | ^
+ // ---.----.----.--- 0
+ // 0 > > > > > > > > nbhoriz
+ // i
+ // [0]
+
+ i = 0;
+ int ilow = 0;
+ int iup = nbhoriz - 1;
+ if (quad->isEdgeOut[3]) { ilow++; } else { if (quad->isEdgeOut[1]) iup--; }
+
+ int jlow = 0;
+ int jup = nbvertic - 1;
+ if (quad->isEdgeOut[0]) { jlow++; } else { if (quad->isEdgeOut[2]) jup--; }
+
+ // regular quadrangles
+ // bool isQuadForward = ( faceIsForward == quad->isEdgeForward[0]);
+ for (i = ilow; i < iup; i++) {
+ for (j = jlow; j < jup; j++) {
+ const SMDS_MeshNode *a, *b, *c, *d;
+ a = quad->uv_grid[j * nbhoriz + i].node;
+ b = quad->uv_grid[j * nbhoriz + i + 1].node;
+ c = quad->uv_grid[(j + 1) * nbhoriz + i + 1].node;
+ d = quad->uv_grid[(j + 1) * nbhoriz + i].node;
+ // if (isQuadForward) faceId = meshDS->AddFace(a,b,c,d);
+ // else faceId = meshDS->AddFace(a,d,c,b);
+ SMDS_MeshFace * face = meshDS->AddFace(a, b, c, d);
+ meshDS->SetMeshElementOnShape(face, F);
+ }
+ }
+
+ UVPtStruct *uv_e0 = quad->uv_edges[0];
+ UVPtStruct *uv_e1 = quad->uv_edges[1];
+ UVPtStruct *uv_e2 = quad->uv_edges[2];
+ UVPtStruct *uv_e3 = quad->uv_edges[3];
+
+ double eps = Precision::Confusion();
+
+ // Boundary quadrangles
+
+ if (quad->isEdgeOut[0]) {
+ // Down edge is out
+ //
+ // |___|___|___|___|___|___|
+ // | | | | | | |
+ // |___|___|___|___|___|___|
+ // | | | | | | |
+ // |___|___|___|___|___|___| __ first row of the regular grid
+ // . . . . . . . . . __ down edge nodes
+ //
+ // >->->->->->->->->->->->-> -- direction of processing
+
+ int g = 0; // number of last processed node in the regular grid
+
+ // number of last node of the down edge to be processed
+ int stop = nbdown - 1;
+ // if right edge is out, we will stop at a node, previous to the last one
+ if (quad->isEdgeOut[1]) stop--;
+
+ // for each node of the down edge find nearest node
+ // in the first row of the regular grid and link them
+ for (i = 0; i < stop; i++) {
+ const SMDS_MeshNode *a, *b, *c, *d;
+ a = uv_e0[i].node;
+ b = uv_e0[i + 1].node;
+ gp_Pnt pb (b->X(), b->Y(), b->Z());
+
+ // find node c in the regular grid, which will be linked with node b
+ int near = g;
+ if (i == stop - 1) {
+ // right bound reached, link with the rightmost node
+ near = iup;
+ c = quad->uv_grid[nbhoriz + iup].node;
+ } else {
+ // find in the grid node c, nearest to the b
+ double mind = RealLast();
+ for (int k = g; k <= iup; k++) {
+
+ const SMDS_MeshNode *nk;
+ if (k < ilow) // this can be, if left edge is out
+ nk = uv_e3[1].node; // get node from the left edge
+ else
+ nk = quad->uv_grid[nbhoriz + k].node; // get one of middle nodes
+
+ gp_Pnt pnk (nk->X(), nk->Y(), nk->Z());
+ double dist = pb.Distance(pnk);
+ if (dist < mind - eps) {
+ c = nk;
+ near = k;
+ mind = dist;
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (near == g) { // make triangle
+ SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
+ meshDS->SetMeshElementOnShape(face, F);
+ } else { // make quadrangle
+ if (near - 1 < ilow)
+ d = uv_e3[1].node;
+ else
+ d = quad->uv_grid[nbhoriz + near - 1].node;
+ SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
+ meshDS->SetMeshElementOnShape(face, F);
+
+ // if node d is not at position g - make additional triangles
+ if (near - 1 > g) {
+ for (int k = near - 1; k > g; k--) {
+ c = quad->uv_grid[nbhoriz + k].node;
+ if (k - 1 < ilow)
+ d = uv_e3[1].node;
+ else
+ d = quad->uv_grid[nbhoriz + k - 1].node;
+ SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
+ meshDS->SetMeshElementOnShape(face, F);
+ }
+ }
+ g = near;
+ }
+ }
+ } else {
+ if (quad->isEdgeOut[2]) {
+ // Up edge is out
+ //
+ // <-<-<-<-<-<-<-<-<-<-<-<-< -- direction of processing
+ //
+ // . . . . . . . . . __ up edge nodes
+ // ___ ___ ___ ___ ___ ___ __ first row of the regular grid
+ // | | | | | | |
+ // |___|___|___|___|___|___|
+ // | | | | | | |
+ // |___|___|___|___|___|___|
+ // | | | | | | |
+
+ int g = nbhoriz - 1; // last processed node in the regular grid
+
+ int stop = 0;
+ // if left edge is out, we will stop at a second node
+ if (quad->isEdgeOut[3]) stop++;
+
+ // for each node of the up edge find nearest node
+ // in the first row of the regular grid and link them
+ for (i = nbup - 1; i > stop; i--) {
+ const SMDS_MeshNode *a, *b, *c, *d;
+ a = uv_e2[i].node;
+ b = uv_e2[i - 1].node;
+ gp_Pnt pb (b->X(), b->Y(), b->Z());
+
+ // find node c in the grid, which will be linked with node b
+ int near = g;
+ if (i == stop + 1) { // left bound reached, link with the leftmost node
+ c = quad->uv_grid[nbhoriz*(nbvertic - 2) + ilow].node;
+ near = ilow;
+ } else {
+ // find node c in the grid, nearest to the b
+ double mind = RealLast();
+ for (int k = g; k >= ilow; k--) {
+ const SMDS_MeshNode *nk;
+ if (k > iup)
+ nk = uv_e1[nbright - 2].node;
+ else
+ nk = quad->uv_grid[nbhoriz*(nbvertic - 2) + k].node;
+ gp_Pnt pnk (nk->X(), nk->Y(), nk->Z());
+ double dist = pb.Distance(pnk);
+ if (dist < mind - eps) {
+ c = nk;
+ near = k;
+ mind = dist;
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (near == g) { // make triangle
+ SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
+ meshDS->SetMeshElementOnShape(face, F);
+ } else { // make quadrangle
+ if (near + 1 > iup)
+ d = uv_e1[nbright - 2].node;
+ else
+ d = quad->uv_grid[nbhoriz*(nbvertic - 2) + near + 1].node;
+ SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
+ meshDS->SetMeshElementOnShape(face, F);
+
+ if (near + 1 < g) { // if d not is at g - make additional triangles
+ for (int k = near + 1; k < g; k++) {
+ c = quad->uv_grid[nbhoriz*(nbvertic - 2) + k].node;
+ if (k + 1 > iup)
+ d = uv_e1[nbright - 2].node;
+ else
+ d = quad->uv_grid[nbhoriz*(nbvertic - 2) + k + 1].node;
+ SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
+ meshDS->SetMeshElementOnShape(face, F);
+ }
+ }
+ g = near;
+ }
+ }
+ }
+ }
+
+ // right or left boundary quadrangles
+ if (quad->isEdgeOut[1]) {
+// MESSAGE("right edge is out");
+ int g = 0; // last processed node in the grid
+ int stop = nbright - 1;
+ if (quad->isEdgeOut[2]) stop--;
+ for (i = 0; i < stop; i++) {
+ const SMDS_MeshNode *a, *b, *c, *d;
+ a = uv_e1[i].node;
+ b = uv_e1[i + 1].node;
+ gp_Pnt pb (b->X(), b->Y(), b->Z());
+
+ // find node c in the grid, nearest to the b
+ int near = g;
+ if (i == stop - 1) { // up bondary reached
+ c = quad->uv_grid[nbhoriz*(jup + 1) - 2].node;
+ near = jup;
+ } else {
+ double mind = RealLast();
+ for (int k = g; k <= jup; k++) {
+ const SMDS_MeshNode *nk;
+ if (k < jlow)
+ nk = uv_e0[nbdown - 2].node;
+ else
+ nk = quad->uv_grid[nbhoriz*(k + 1) - 2].node;
+ gp_Pnt pnk (nk->X(), nk->Y(), nk->Z());
+ double dist = pb.Distance(pnk);
+ if (dist < mind - eps) {
+ c = nk;
+ near = k;
+ mind = dist;
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (near == g) { // make triangle
+ SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
+ meshDS->SetMeshElementOnShape(face, F);
+ } else { // make quadrangle
+ if (near - 1 < jlow)
+ d = uv_e0[nbdown - 2].node;
+ else
+ d = quad->uv_grid[nbhoriz*near - 2].node;
+ SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
+ meshDS->SetMeshElementOnShape(face, F);
+
+ if (near - 1 > g) { // if d not is at g - make additional triangles
+ for (int k = near - 1; k > g; k--) {
+ c = quad->uv_grid[nbhoriz*(k + 1) - 2].node;
+ if (k - 1 < jlow)
+ d = uv_e0[nbdown - 2].node;
+ else
+ d = quad->uv_grid[nbhoriz*k - 2].node;
+ SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
+ meshDS->SetMeshElementOnShape(face, F);
+ }
+ }
+ g = near;
+ }
+ }
+ } else {
+ if (quad->isEdgeOut[3]) {
+// MESSAGE("left edge is out");
+ int g = nbvertic - 1; // last processed node in the grid
+ int stop = 0;
+ if (quad->isEdgeOut[0]) stop++;
+ for (i = nbleft - 1; i > stop; i--) {
+ const SMDS_MeshNode *a, *b, *c, *d;
+ a = uv_e3[i].node;
+ b = uv_e3[i - 1].node;
+ gp_Pnt pb (b->X(), b->Y(), b->Z());
+
+ // find node c in the grid, nearest to the b
+ int near = g;
+ if (i == stop + 1) { // down bondary reached
+ c = quad->uv_grid[nbhoriz*jlow + 1].node;
+ near = jlow;
+ } else {
+ double mind = RealLast();
+ for (int k = g; k >= jlow; k--) {
+ const SMDS_MeshNode *nk;
+ if (k > jup)
+ nk = uv_e2[1].node;
+ else
+ nk = quad->uv_grid[nbhoriz*k + 1].node;
+ gp_Pnt pnk (nk->X(), nk->Y(), nk->Z());
+ double dist = pb.Distance(pnk);
+ if (dist < mind - eps) {
+ c = nk;
+ near = k;
+ mind = dist;
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (near == g) { // make triangle
+ SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
+ meshDS->SetMeshElementOnShape(face, F);
+ } else { // make quadrangle
+ if (near + 1 > jup)
+ d = uv_e2[1].node;
+ else
+ d = quad->uv_grid[nbhoriz*(near + 1) + 1].node;
+ SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
+ meshDS->SetMeshElementOnShape(face, F);
+
+ if (near + 1 < g) { // if d not is at g - make additional triangles
+ for (int k = near + 1; k < g; k++) {
+ c = quad->uv_grid[nbhoriz*k + 1].node;
+ if (k + 1 > jup)
+ d = uv_e2[1].node;
+ else
+ d = quad->uv_grid[nbhoriz*(k + 1) + 1].node;
+ SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
+ meshDS->SetMeshElementOnShape(face, F);
+ }
+ }
+ g = near;
+ }
+ }
+ }
+ }
+
+ QuadDelete(quad);
+ bool isOk = true;
+ return isOk;