Salome HOME
Fix crash at study closing. Enable canceling Prism 3D computation
[modules/smesh.git] / src / StdMeshers / StdMeshers_Prism_3D.cxx
index 79fd9f82e0e7d49f4c043ddfe1384632f4390f8f..afac9bebe4ec2cc0f4dad6359f90c5ccb5a9aa2f 100644 (file)
 using namespace std;
 
 #define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
-#define gpXYZ(n) gp_XYZ(n->X(),n->Y(),n->Z())
-#define SHOWYXZ(msg, xyz) // {\
-// gp_Pnt p (xyz); \
-// cout << msg << " ("<< p.X() << "; " <<p.Y() << "; " <<p.Z() << ") " <<endl;\
-// }
+#define gpXYZ(n) SMESH_TNodeXYZ(n)
+
 #ifdef _DEBUG_
 #define DBGOUT(msg) //cout << msg << endl;
+#define SHOWYXZ(msg, xyz)                                               \
+  // { gp_Pnt p (xyz);                                                     \
+  //   cout << msg << " ("<< p.X() << "; " <<p.Y() << "; " <<p.Z() << ") " <<endl; }
 #else
 #define DBGOUT(msg)
+#define SHOWYXZ(msg, xyz)
 #endif
 
 namespace TAssocTool = StdMeshers_ProjectionUtils;
@@ -190,7 +191,7 @@ namespace {
             ( sm->NbElements() > 0 ) &&
             ( !theHelper.IsSameElemGeometry( sm, SMDSGeom_QUADRANGLE ) ))
         {
-          faceFound;
+          faceFound = true;
           break;
         }
       if ( !faceFound )
@@ -212,6 +213,7 @@ namespace {
     quad->side[ QUAD_TOP_SIDE  ].grid->Reverse();
     quad->side[ QUAD_LEFT_SIDE ].grid->Reverse();
     int edgeIndex = 0;
+    bool isComposite = false;
     for ( size_t i = 0; i < quad->side.size(); ++i )
     {
       StdMeshers_FaceSidePtr quadSide = quad->side[i];
@@ -219,7 +221,7 @@ namespace {
         if ( botE.IsSame( quadSide->Edge( iE )))
         {
           if ( quadSide->NbEdges() > 1 )
-            return false;
+            isComposite = true; //return false;
           edgeIndex = i;
           i = quad->side.size(); // to quit from the outer loop
           break;
@@ -230,7 +232,7 @@ namespace {
 
     quad->face = TopoDS::Face( face );
 
-    return true;
+    return !isComposite;
   }
 
   //================================================================================
@@ -425,10 +427,10 @@ namespace {
    */
   //================================================================================
 
-  double normAngle(const TopoDS_Edge & E1, const TopoDS_Edge & E2, const TopoDS_Face & F)
-  {
-    return SMESH_MesherHelper::GetAngle( E1, E2, F ) / ( 0.5 * M_PI );
-  }
+  // double normAngle(const TopoDS_Edge & E1, const TopoDS_Edge & E2, const TopoDS_Face & F)
+  // {
+  //   return SMESH_MesherHelper::GetAngle( E1, E2, F ) / ( 0.5 * M_PI );
+  // }
 
   //================================================================================
   /*!
@@ -654,6 +656,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
   meshedFaces.splice( meshedFaces.begin(), notQuadMeshedFaces );
 
   Prism_3D::TPrismTopo prism;
+  myPropagChains = 0;
 
   if ( nbSolids == 1 )
   {
@@ -905,10 +908,17 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
           if ( !quadList.back() )
             return toSM( error(TCom("Side face #") << shapeID( face )
                                << " not meshable with quadrangles"));
-          if ( ! setBottomEdge( *edge, quadList.back(), face ))
-            return toSM( error(TCom("Composite 'horizontal' edges are not supported")));
-          thePrism.myWallQuads.push_back( quadList );
-          faceMap.Add( face );
+          bool isCompositeBase = ! setBottomEdge( *edge, quadList.back(), face );
+          if ( isCompositeBase )
+          {
+            // it's OK if all EDGEs of the bottom side belongs to the bottom FACE
+            StdMeshers_FaceSidePtr botSide = quadList.back()->side[ QUAD_BOTTOM_SIDE ];
+            for ( int iE = 0; iE < botSide->NbEdges(); ++iE )
+              if ( !myHelper->IsSubShape( botSide->Edge(iE), thePrism.myBottom ))
+                return toSM( error(TCom("Composite 'horizontal' edges are not supported")));
+          }
+          if ( faceMap.Add( face ))
+            thePrism.myWallQuads.push_back( quadList );
           break;
         }
       }
@@ -1076,7 +1086,7 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
   // Projections on the top and bottom faces are taken from nodes existing
   // on these faces; find correspondence between bottom and top nodes
   myBotToColumnMap.clear();
-  if ( !assocOrProjBottom2Top( bottomToTopTrsf ) ) // it also fills myBotToColumnMap
+  if ( !assocOrProjBottom2Top( bottomToTopTrsf, thePrism ) ) // it also fills myBotToColumnMap
     return false;
 
 
@@ -1193,6 +1203,9 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
         // create a node
         node = meshDS->AddNode( coords.X(), coords.Y(), coords.Z() );
         meshDS->SetNodeInVolume( node, volumeID );
+
+        if ( _computeCanceled )
+          return false;
       }
     } // loop on bottom nodes
   }
@@ -1254,34 +1267,36 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
   TProjction1dAlgo*      projector1D = TProjction1dAlgo::instance( this );
   StdMeshers_Quadrangle_2D* quadAlgo = TQuadrangleAlgo::instance( this, myHelper );
 
-  SMESH_HypoFilter hyp1dFilter( SMESH_HypoFilter::IsAlgo(),/*not=*/true);
-  hyp1dFilter.And( SMESH_HypoFilter::HasDim( 1 ));
-  hyp1dFilter.And( SMESH_HypoFilter::IsMoreLocalThan( thePrism.myShape3D, *mesh ));
+  // SMESH_HypoFilter hyp1dFilter( SMESH_HypoFilter::IsAlgo(),/*not=*/true);
+  // hyp1dFilter.And( SMESH_HypoFilter::HasDim( 1 ));
+  // hyp1dFilter.And( SMESH_HypoFilter::IsMoreLocalThan( thePrism.myShape3D, *mesh ));
 
   // Discretize equally 'vertical' EDGEs
   // -----------------------------------
   // find source FACE sides for projection: either already computed ones or
   // the 'most composite' ones
-  multimap< int, int > wgt2quad;
-  for ( size_t iW = 0; iW != thePrism.myWallQuads.size(); ++iW )
+  const size_t nbWalls = thePrism.myWallQuads.size();
+  vector< int > wgt( nbWalls, 0 ); // "weight" of a wall
+  for ( size_t iW = 0; iW != nbWalls; ++iW )
   {
     Prism_3D::TQuadList::const_iterator quad = thePrism.myWallQuads[iW].begin();
-    int wgt = 0; // "weight"
     for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
     {
       StdMeshers_FaceSidePtr lftSide = (*quad)->side[ QUAD_LEFT_SIDE ];
       for ( int i = 0; i < lftSide->NbEdges(); ++i )
       {
-        ++wgt;
+        ++wgt[ iW ];
         const TopoDS_Edge& E = lftSide->Edge(i);
         if ( mesh->GetSubMesh( E )->IsMeshComputed() )
-          wgt += 10;
-        else if ( mesh->GetHypothesis( E, hyp1dFilter, true )) // local hypothesis!
-          wgt += 100;
+        {
+          wgt[ iW ] += 100;
+          wgt[ myHelper->WrapIndex( iW+1, nbWalls)] += 10;
+          wgt[ myHelper->WrapIndex( iW-1, nbWalls)] += 10;
+        }
+        // else if ( mesh->GetHypothesis( E, hyp1dFilter, true )) // local hypothesis!
+        //   wgt += 100;
       }
     }
-    wgt2quad.insert( make_pair( wgt, iW ));
-
     // in quadratic mesh, pass ignoreMediumNodes to quad sides
     if ( myHelper->GetIsQuadratic() )
     {
@@ -1291,6 +1306,9 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
           (*quad)->side[ i ].grid->SetIgnoreMediumNodes( true );
     }
   }
+  multimap< int, int > wgt2quad;
+  for ( size_t iW = 0; iW != nbWalls; ++iW )
+    wgt2quad.insert( make_pair( wgt[ iW ], iW ));
 
   // Project 'vertical' EDGEs, from left to right
   multimap< int, int >::reverse_iterator w2q = wgt2quad.rbegin();
@@ -1339,7 +1357,11 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
       {
         const TopoDS_Edge& tgtE = rgtSide->Edge(i);
         SMESH_subMesh*    tgtSM = mesh->GetSubMesh( tgtE );
-        if (( isTgtEdgeComputed[ i ] = tgtSM->IsMeshComputed() )) {
+        if ( !( isTgtEdgeComputed[ i ] = tgtSM->IsMeshComputed() )) {
+          tgtSM->ComputeSubMeshStateEngine( SMESH_subMesh::COMPUTE );
+          tgtSM->ComputeStateEngine       ( SMESH_subMesh::COMPUTE );
+        }
+        if ( tgtSM->IsMeshComputed() ) {
           ++nbTgtMeshed;
           nbTgtSegments += tgtSM->GetSubMeshDS()->NbElements();
         }
@@ -1348,16 +1370,33 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
       {
         if ( nbTgtSegments != nbSrcSegments )
         {
-          for ( int i = 0; i < lftSide->NbEdges(); ++i )
-            addBadInputElements( meshDS->MeshElements( lftSide->Edge( i )));
+          bool badMeshRemoved = false;
+          // remove just computed segments
           for ( int i = 0; i < rgtSide->NbEdges(); ++i )
-            addBadInputElements( meshDS->MeshElements( rgtSide->Edge( i )));
-          return toSM( error( TCom("Different nb of segment on logically vertical edges #")
-                              << shapeID( lftSide->Edge(0) ) << " and #"
-                              << shapeID( rgtSide->Edge(0) ) << ": "
-                              << nbSrcSegments << " != " << nbTgtSegments ));
+            if ( !isTgtEdgeComputed[ i ])
+            {
+              const TopoDS_Edge& tgtE = rgtSide->Edge(i);
+              SMESH_subMesh*    tgtSM = mesh->GetSubMesh( tgtE );
+              tgtSM->ComputeStateEngine( SMESH_subMesh::CLEAN );
+              badMeshRemoved = true;
+              nbTgtMeshed--;
+            }
+          if ( !badMeshRemoved )
+          {
+            for ( int i = 0; i < lftSide->NbEdges(); ++i )
+              addBadInputElements( meshDS->MeshElements( lftSide->Edge( i )));
+            for ( int i = 0; i < rgtSide->NbEdges(); ++i )
+              addBadInputElements( meshDS->MeshElements( rgtSide->Edge( i )));
+            return toSM( error( TCom("Different nb of segment on logically vertical edges #")
+                                << shapeID( lftSide->Edge(0) ) << " and #"
+                                << shapeID( rgtSide->Edge(0) ) << ": "
+                                << nbSrcSegments << " != " << nbTgtSegments ));
+          }
+        }
+        else // if ( nbTgtSegments == nbSrcSegments )
+        {
+          continue;
         }
-        continue;
       }
       // Compute 'vertical projection'
       if ( nbTgtMeshed == 0 )
@@ -1399,13 +1438,22 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
             // new nodes are on different EDGEs; put one of them on VERTEX
             const int      edgeIndex = rgtSide->EdgeIndex( srcNodeStr[ iN-1 ].normParam );
             const double vertexParam = rgtSide->LastParameter( edgeIndex );
-            const gp_Pnt           p = BRep_Tool::Pnt( rgtSide->LastVertex( edgeIndex ));
+            TopoDS_Vertex     vertex = rgtSide->LastVertex( edgeIndex );
+            const SMDS_MeshNode*  vn = SMESH_Algo::VertexNode( vertex, meshDS );
+            const gp_Pnt           p = BRep_Tool::Pnt( vertex );
             const int         isPrev = ( Abs( srcNodeStr[ iN-1 ].normParam - vertexParam ) <
                                          Abs( srcNodeStr[ iN   ].normParam - vertexParam ));
             meshDS->UnSetNodeOnShape( newNodes[ iN-isPrev ] );
-            meshDS->SetNodeOnVertex ( newNodes[ iN-isPrev ], rgtSide->LastVertex( edgeIndex ));
+            meshDS->SetNodeOnVertex ( newNodes[ iN-isPrev ], vertex );
             meshDS->MoveNode        ( newNodes[ iN-isPrev ], p.X(), p.Y(), p.Z() );
             id2type.first = newNodes[ iN-(1-isPrev) ]->getshapeId();
+            if ( vn )
+            {
+              SMESH_MeshEditor::TListOfListOfNodes lln( 1, list< const SMDS_MeshNode* >() );
+              lln.back().push_back ( vn );
+              lln.back().push_front( newNodes[ iN-isPrev ] ); // to keep 
+              SMESH_MeshEditor( mesh ).MergeNodes( lln );
+            }
           }
           SMDS_MeshElement* newEdge = myHelper->AddEdge( newNodes[ iN-1 ], newNodes[ iN ] );
           meshDS->SetMeshElementOnShape( newEdge, id2type.first );
@@ -1442,10 +1490,13 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
     Prism_3D::TQuadList::const_iterator quad = thePrism.myWallQuads[iW].begin();
     for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
     {
-      // Top EDGEs must be projections from the bottom ones
-      // to compute stuctured quad mesh on wall FACEs
-      // ---------------------------------------------------
+      const TopoDS_Face& face = (*quad)->face;
+      SMESH_subMesh* fSM = mesh->GetSubMesh( face );
+      if ( ! fSM->IsMeshComputed() )
       {
+        // Top EDGEs must be projections from the bottom ones
+        // to compute stuctured quad mesh on wall FACEs
+        // ---------------------------------------------------
         const TopoDS_Edge& botE = (*quad)->side[ QUAD_BOTTOM_SIDE ].grid->Edge(0);
         const TopoDS_Edge& topE = (*quad)->side[ QUAD_TOP_SIDE    ].grid->Edge(0);
         SMESH_subMesh*    botSM = mesh->GetSubMesh( botE );
@@ -1502,14 +1553,11 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
           }
         }
         tgtSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
-      }
 
-      // Compute quad mesh on wall FACEs
-      // -------------------------------
-      const TopoDS_Face& face = (*quad)->face;
-      SMESH_subMesh* fSM = mesh->GetSubMesh( face );
-      if ( ! fSM->IsMeshComputed() )
-      {
+
+        // Compute quad mesh on wall FACEs
+        // -------------------------------
+
         // make all EDGES meshed
         fSM->ComputeSubMeshStateEngine( SMESH_subMesh::COMPUTE );
         if ( !fSM->SubMeshesComputed() )
@@ -1545,9 +1593,10 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
 
 TopoDS_Edge StdMeshers_Prism_3D::findPropagationSource( const TopoDS_Edge& E )
 {
-  for ( size_t i = 0; !myPropagChains[i].IsEmpty(); ++i )
-    if ( myPropagChains[i].Contains( E ))
-      return TopoDS::Edge( myPropagChains[i].FindKey( 1 ));
+  if ( myPropagChains )
+    for ( size_t i = 0; !myPropagChains[i].IsEmpty(); ++i )
+      if ( myPropagChains[i].Contains( E ))
+        return TopoDS::Edge( myPropagChains[i].FindKey( 1 ));
 
   return TopoDS_Edge();
 }
@@ -1801,7 +1850,8 @@ void StdMeshers_Prism_3D::AddPrisms( vector<const TNodeColumn*> & columns,
  */
 //================================================================================
 
-bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf )
+bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf,
+                                                 const Prism_3D::TPrismTopo& thePrism)
 {
   SMESH_subMesh * botSM = myBlock.SubMesh( ID_BOT_FACE );
   SMESH_subMesh * topSM = myBlock.SubMesh( ID_TOP_FACE );
@@ -1811,14 +1861,14 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
 
   if ( !botSMDS || botSMDS->NbElements() == 0 )
   {
-    _gen->Compute( *myHelper->GetMesh(), botSM->GetSubShape() );
+    _gen->Compute( *myHelper->GetMesh(), botSM->GetSubShape(), /*aShapeOnly=*/true );
     botSMDS = botSM->GetSubMeshDS();
     if ( !botSMDS || botSMDS->NbElements() == 0 )
       return toSM( error(TCom("No elements on face #") << botSM->GetId() ));
   }
 
   bool needProject = !topSM->IsMeshComputed();
-  if ( !needProject && 
+  if ( !needProject &&
        (botSMDS->NbElements() != topSMDS->NbElements() ||
         botSMDS->NbNodes()    != topSMDS->NbNodes()))
   {
@@ -1844,19 +1894,70 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
   TopoDS_Face topFace = TopoDS::Face( myBlock.Shape( ID_TOP_FACE ));
   // associate top and bottom faces
   TAssocTool::TShapeShapeMap shape2ShapeMap;
-  if ( !TAssocTool::FindSubShapeAssociation( botFace, myBlock.Mesh(),
-                                             topFace, myBlock.Mesh(),
-                                             shape2ShapeMap) )
-    return toSM( error(TCom("Topology of faces #") << botSM->GetId()
-                       <<" and #"<< topSM->GetId() << " seems different" ));
+  const bool sameTopo = 
+    TAssocTool::FindSubShapeAssociation( botFace, myBlock.Mesh(),
+                                         topFace, myBlock.Mesh(),
+                                         shape2ShapeMap);
+  if ( !sameTopo )
+    for ( size_t iQ = 0; iQ < thePrism.myWallQuads.size(); ++iQ )
+    {
+      const Prism_3D::TQuadList& quadList = thePrism.myWallQuads[iQ];
+      StdMeshers_FaceSidePtr      botSide = quadList.front()->side[ QUAD_BOTTOM_SIDE ];
+      StdMeshers_FaceSidePtr      topSide = quadList.back ()->side[ QUAD_TOP_SIDE ];
+      if ( botSide->NbEdges() == topSide->NbEdges() )
+      {
+        for ( int iE = 0; iE < botSide->NbEdges(); ++iE )
+        {
+          TAssocTool::InsertAssociation( botSide->Edge( iE ),
+                                         topSide->Edge( iE ), shape2ShapeMap );
+          TAssocTool::InsertAssociation( myHelper->IthVertex( 0, botSide->Edge( iE )),
+                                         myHelper->IthVertex( 0, topSide->Edge( iE )),
+                                         shape2ShapeMap );
+        }
+      }
+      else
+      {
+        TopoDS_Vertex vb, vt;
+        StdMeshers_FaceSidePtr sideB, sideT;
+        vb = myHelper->IthVertex( 0, botSide->Edge( 0 ));
+        vt = myHelper->IthVertex( 0, topSide->Edge( 0 ));
+        sideB = quadList.front()->side[ QUAD_LEFT_SIDE ];
+        sideT = quadList.back ()->side[ QUAD_LEFT_SIDE ];
+        if ( vb.IsSame( sideB->FirstVertex() ) &&
+             vt.IsSame( sideT->LastVertex() ))
+        {
+          TAssocTool::InsertAssociation( botSide->Edge( 0 ),
+                                         topSide->Edge( 0 ), shape2ShapeMap );
+          TAssocTool::InsertAssociation( vb, vt, shape2ShapeMap );
+        }
+        vb = myHelper->IthVertex( 1, botSide->Edge( botSide->NbEdges()-1 ));
+        vt = myHelper->IthVertex( 1, topSide->Edge( topSide->NbEdges()-1 ));
+        sideB = quadList.front()->side[ QUAD_RIGHT_SIDE ];
+        sideT = quadList.back ()->side[ QUAD_RIGHT_SIDE ];
+        if ( vb.IsSame( sideB->FirstVertex() ) &&
+             vt.IsSame( sideT->LastVertex() ))
+        {
+          TAssocTool::InsertAssociation( botSide->Edge( botSide->NbEdges()-1 ),
+                                         topSide->Edge( topSide->NbEdges()-1 ),
+                                         shape2ShapeMap );
+          TAssocTool::InsertAssociation( vb, vt, shape2ShapeMap );
+        }
+      }
+    }
 
   // Find matching nodes of top and bottom faces
   TNodeNodeMap n2nMap;
   if ( ! TAssocTool::FindMatchingNodesOnFaces( botFace, myBlock.Mesh(),
                                                topFace, myBlock.Mesh(),
                                                shape2ShapeMap, n2nMap ))
-    return toSM( error(TCom("Mesh on faces #") << botSM->GetId()
-                       <<" and #"<< topSM->GetId() << " seems different" ));
+  {
+    if ( sameTopo )
+      return toSM( error(TCom("Mesh on faces #") << botSM->GetId()
+                         <<" and #"<< topSM->GetId() << " seems different" ));
+    else
+      return toSM( error(TCom("Topology of faces #") << botSM->GetId()
+                         <<" and #"<< topSM->GetId() << " seems different" ));
+  }
 
   // Fill myBotToColumnMap
 
@@ -2496,6 +2597,29 @@ namespace Prism_3D
     myWallQuads.clear();
   }
 
+  //================================================================================
+  /*!
+   * \brief Set upside-down
+   */
+  //================================================================================
+
+  void TPrismTopo::SetUpsideDown()
+  {
+    std::swap( myBottom, myTop );
+    myBottomEdges.clear();
+    std::reverse( myBottomEdges.begin(), myBottomEdges.end() );
+    for ( size_t i = 0; i < myWallQuads.size(); ++i )
+    {
+      myWallQuads[i].reverse();
+      TQuadList::iterator q = myWallQuads[i].begin();
+      for ( ; q != myWallQuads[i].end(); ++q )
+      {
+        (*q)->shift( 2, /*keepUnitOri=*/true );
+      }
+      myBottomEdges.push_back( myWallQuads[i].front()->side[ QUAD_BOTTOM_SIDE ].grid->Edge(0) );
+    }
+  }
+
 } // namespace Prism_3D
 
 //================================================================================
@@ -2602,7 +2726,7 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
   SMESH_subMesh * botSM = 0;
   SMESH_subMesh * topSM = 0;
 
-  if ( hasNotQuad ) // can chose a bottom FACE
+  if ( hasNotQuad ) // can choose a bottom FACE
   {
     if ( nbNotQuadMeshed > 0 ) botSM = notQuadElemSubMesh.front();
     else                       botSM = notQuadGeomSubMesh.front();
@@ -2710,6 +2834,12 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
                       "Non-quadrilateral faces are not opposite"));
   }
 
+  if ( thePrism.myBottomEdges.size() > thePrism.myWallQuads.size() )
+  {
+    // composite bottom sides => set thePrism upside-down
+    thePrism.SetUpsideDown();
+  }
+
   return true;
 }
 
@@ -3634,8 +3764,8 @@ gp_Pnt StdMeshers_PrismAsBlock::TSideFace::Value(const Standard_Real U,
     }
     if ( !edge.IsNull() )
     {
-      double u1 = myHelper.GetNodeU( edge, nn[0] );
-      double u3 = myHelper.GetNodeU( edge, nn[2] );
+      double u1 = myHelper.GetNodeU( edge, nn[0], nn[2] );
+      double u3 = myHelper.GetNodeU( edge, nn[2], nn[0] );
       double u = u1 * ( 1 - hR ) + u3 * hR;
       TopLoc_Location loc; double f,l;
       Handle(Geom_Curve) curve = BRep_Tool::Curve( edge,loc,f,l );