@@ -261,34 +261,103 @@ const importGmshQuadTri = async (file) => {
261261 if ( ! result . boundaryElements [ prop . tag ] ) {
262262 result . boundaryElements [ prop . tag ] = [ ] ;
263263 }
264- // TODO: Calculate the boundaryElements based on boundaryElementsByTag and nodalNumbering
265- // NEXT TODO: Remap nodalNumbering according to https://gmsh.info/doc/texinfo/gmsh.html#Node-ordering.
266- // In the case of quadrilaterals, the order is:
267- /**
268- * Gmsh quadrilateral node numbering (linear elements):
269- *
270- * 3__ __2
271- * | |
272- * |__ __|
273- * 0 1
274- *
275- * FEAScript quadrilateral node numbering:
276- *
277- * 1__ __3
278- * | |
279- * |__ __|
280- * 0 2
281- *
282- * Remapping:
283- * - 0 (bottom left): stays as 0
284- * - 3 (top left): becomes 1
285- * - 1 (bottom right): becomes 2
286- * - 2 (top right): becomes 3
287- */
264+
265+ // For each boundary line segment (2 nodes)
266+ boundaryNodes . forEach ( ( nodesPair ) => {
267+ // Find which quad element contains both nodes of this boundary
268+ let foundElement = false ;
269+ for ( let elemIdx = 0 ; elemIdx < result . nodalNumbering . quadElements . length ; elemIdx ++ ) {
270+ const elemNodes = result . nodalNumbering . quadElements [ elemIdx ] ;
271+
272+ // Check if both boundary nodes are in this element
273+ if ( elemNodes . includes ( nodesPair [ 0 ] ) && elemNodes . includes ( nodesPair [ 1 ] ) ) {
274+ // Find which side of the element these nodes form
275+ let side ;
276+
277+ // For linear quadrilateral elements, the Gmsh local numbering is:
278+ // 3 --- 2
279+ // | |
280+ // 0 --- 1
281+
282+ // Check which side these nodes belong to
283+ if (
284+ ( elemNodes . indexOf ( nodesPair [ 0 ] ) === 0 && elemNodes . indexOf ( nodesPair [ 1 ] ) === 1 ) ||
285+ ( elemNodes . indexOf ( nodesPair [ 1 ] ) === 0 && elemNodes . indexOf ( nodesPair [ 0 ] ) === 1 )
286+ ) {
287+ side = 0 ; // Bottom side
288+ } else if (
289+ ( elemNodes . indexOf ( nodesPair [ 0 ] ) === 1 && elemNodes . indexOf ( nodesPair [ 1 ] ) === 2 ) ||
290+ ( elemNodes . indexOf ( nodesPair [ 1 ] ) === 1 && elemNodes . indexOf ( nodesPair [ 0 ] ) === 2 )
291+ ) {
292+ side = 1 ; // Right side
293+ } else if (
294+ ( elemNodes . indexOf ( nodesPair [ 0 ] ) === 2 && elemNodes . indexOf ( nodesPair [ 1 ] ) === 3 ) ||
295+ ( elemNodes . indexOf ( nodesPair [ 1 ] ) === 2 && elemNodes . indexOf ( nodesPair [ 0 ] ) === 3 )
296+ ) {
297+ side = 2 ; // Top side
298+ } else if (
299+ ( elemNodes . indexOf ( nodesPair [ 0 ] ) === 3 && elemNodes . indexOf ( nodesPair [ 1 ] ) === 0 ) ||
300+ ( elemNodes . indexOf ( nodesPair [ 1 ] ) === 3 && elemNodes . indexOf ( nodesPair [ 0 ] ) === 0 )
301+ ) {
302+ side = 3 ; // Left side
303+ }
304+
305+ // Add to boundary elements
306+ result . boundaryElements [ prop . tag ] . push ( [ elemIdx , side ] ) ;
307+ foundElement = true ;
308+ break ;
309+ }
310+ }
311+ } ) ;
288312 }
289313 }
290314 } ) ;
291315
316+ // Remap nodal numbering from Gmsh format to FEAScript format for quadrilateral elements
317+ if ( result . nodalNumbering . quadElements . length > 0 ) {
318+ /*
319+ * Gmsh quadrilateral node numbering (linear elements):
320+ *
321+ * 3__ __2
322+ * | |
323+ * |__ __|
324+ * 0 1
325+ *
326+ * FEAScript quadrilateral node numbering (linear elements):
327+ *
328+ * 1__ __3
329+ * | |
330+ * |__ __|
331+ * 0 2
332+ *
333+ */
334+ // Mapping: Gmsh → FEAScript
335+ // 0 → 0 (bottom left)
336+ // 1 → 2 (bottom right)
337+ // 2 → 3 (top right)
338+ // 3 → 1 (top left)
339+ const gmshToFEAMap = [ 0 , 2 , 3 , 1 ] ;
340+
341+ for ( let i = 0 ; i < result . nodalNumbering . quadElements . length ; i ++ ) {
342+ const originalNodes = [ ...result . nodalNumbering . quadElements [ i ] ] ;
343+ for ( let j = 0 ; j < 4 ; j ++ ) {
344+ result . nodalNumbering . quadElements [ i ] [ gmshToFEAMap [ j ] ] = originalNodes [ j ] ;
345+ }
346+ }
347+ }
348+
349+ // Fix boundary elements array - remove the empty first element
350+ if ( result . boundaryElements . length > 0 && result . boundaryElements [ 0 ] === undefined ) {
351+ // Create a new array without the empty first element
352+ const fixedBoundaryElements = [ ] ;
353+ for ( let i = 1 ; i < result . boundaryElements . length ; i ++ ) {
354+ if ( result . boundaryElements [ i ] ) {
355+ fixedBoundaryElements . push ( result . boundaryElements [ i ] ) ;
356+ }
357+ }
358+ result . boundaryElements = fixedBoundaryElements ;
359+ }
360+
292361 return result ;
293362} ;
294363
0 commit comments