3737)
3838from iso2mesh .geometry import meshabox
3939from iso2mesh .volume import volgrow , fillholes3d
40- from iso2mesh .line import polylineinterp , polylinelen , polylinesimplify , closestnode
40+ from iso2mesh .line import (
41+ polylineinterp ,
42+ polylinelen ,
43+ polylinesimplify ,
44+ closestnode ,
45+ maxloop ,
46+ )
4147from iso2mesh .plot import plotmesh
4248
4349from typing import Tuple , Dict , Union , Optional , List
@@ -1367,11 +1373,54 @@ def brain1020(
13671373 landmarks ["cz" ],
13681374 ]
13691375 )
1370-
1376+ else :
1377+ landmarks = {
1378+ "nz" : initpoints [0 , :],
1379+ "iz" : initpoints [1 , :],
1380+ "lpa" : initpoints [2 , :],
1381+ "rpa" : initpoints [3 , :],
1382+ "cz" : initpoints [4 , :],
1383+ }
13711384 # Convert tetrahedral mesh into a surface mesh
13721385 if face .shape [1 ] >= 4 :
13731386 face = volface (face [:, :4 ])[0 ] # Use first 4 columns for tetrahedral faces
13741387
1388+ if kwargs .get ("clean" , 1 ):
1389+ # Find the bounding box of the top part of the head, and remove all other triangles
1390+ p0 = landmarks .copy ()
1391+
1392+ v_ni = p0 ["nz" ] - p0 ["iz" ]
1393+ v_lr = p0 ["lpa" ] - p0 ["rpa" ]
1394+ v_cz0 = np .cross (v_ni , v_lr )
1395+ v_cz0 = v_cz0 / np .linalg .norm (v_cz0 )
1396+ v_cn = p0 ["cz" ] - p0 ["nz" ]
1397+ d_czlpa = np .dot (p0 ["cz" ] - p0 ["lpa" ], v_cz0 )
1398+ d_cznz = np .dot (v_cn , v_cz0 )
1399+
1400+ if abs (d_czlpa ) > abs (d_cznz ): # if lpa is further away from cz than nz
1401+ # Move nz to the same level as lpa, can also add rpa
1402+ p0 ["nz" ] = p0 ["nz" ] - v_cz0 * (abs (d_czlpa ) - abs (d_cznz ))
1403+ # Move iz to the same level as lpa, can also add rpa
1404+ p0 ["iz" ] = p0 ["iz" ] - v_cz0 * (abs (d_czlpa ) - abs (d_cznz ))
1405+
1406+ v_cz = d_cznz * v_cz0
1407+ bbx0 = p0 ["nz" ] - 0.6 * v_lr - 0.1 * v_cz + 0.1 * v_ni
1408+
1409+ # Calculate mesh centroids
1410+ c0 = meshcentroid (node , face )
1411+
1412+ # Calculate distance from bounding box plane
1413+ v_cz0_rep = np .tile (
1414+ v_cz0 , (face .shape [0 ], 1 )
1415+ ) # repmat(v_cz0, size(face, 1), 1)
1416+ bbx0_rep = np .tile (bbx0 , (face .shape [0 ], 1 )) # repmat(bbx0, size(face, 1), 1)
1417+ dz = np .sum (v_cz0_rep * (c0 - bbx0_rep ), axis = 1 )
1418+
1419+ # Filter faces - keep only those with dz > 0
1420+ face = face [dz > 0 , :]
1421+
1422+ del p0 , bbx0 , c0 , dz
1423+
13751424 # Remove nodes not located in the surface
13761425 node , face , _ = removeisolatednode (node , face )
13771426
@@ -1387,16 +1436,6 @@ def brain1020(
13871436 print ("Initial points:" )
13881437 print (initpoints )
13891438
1390- # Save input initpoints to landmarks output, cz is not finalized
1391- if initpoints .shape [0 ] >= 5 :
1392- landmarks = {
1393- "nz" : initpoints [0 , :],
1394- "iz" : initpoints [1 , :],
1395- "lpa" : initpoints [2 , :],
1396- "rpa" : initpoints [3 , :],
1397- "cz" : initpoints [4 , :],
1398- }
1399-
14001439 # At this point, initpoints contains {nz, iz, lpa, rpa, cz0}
14011440 # Plot the head mesh
14021441 if showplot :
@@ -1417,7 +1456,8 @@ def brain1020(
14171456 while np .linalg .norm (initpoints [4 , :] - lastcz ) > tol and cziter < maxcziter :
14181457
14191458 # Step 1: nz, iz and cz0 to determine saggital reference curve
1420- nsagg = slicesurf (node , face , initpoints [[0 , 1 , 4 ], :])
1459+ nsagg , curveloop , _ = slicesurf (node , face , initpoints [[0 , 1 , 4 ], :], full = True )
1460+ nsagg = nsagg [maxloop (curveloop ) - 1 , :]
14211461
14221462 # Step 1.1: get cz1 as the mid-point between iz and nz
14231463 slen , nsagg , _ = polylinelen (
@@ -1429,7 +1469,11 @@ def brain1020(
14291469 initpoints [4 , :] = cz [0 , :]
14301470
14311471 # Step 1.2: lpa, rpa and cz1 to determine coronal reference curve, update cz1
1432- curves ["cm" ] = slicesurf (node , face , initpoints [[2 , 3 , 4 ], :])
1472+ curves ["cm" ], curveloop , _ = slicesurf (
1473+ node , face , initpoints [[2 , 3 , 4 ], :], full = True
1474+ )
1475+ curves ["cm" ] = curves ["cm" ][maxloop (curveloop ) - 1 , :]
1476+
14331477 len_cm , curves ["cm" ], _ = polylinelen (
14341478 curves ["cm" ], initpoints [2 , :], initpoints [3 , :], initpoints [4 , :]
14351479 )
@@ -1458,7 +1502,11 @@ def brain1020(
14581502 )
14591503 landmarks ["cm" ] = coro # t7, c3, cz, c4, t8
14601504
1461- curves ["sm" ] = slicesurf (node , face , initpoints [[0 , 1 , 4 ], :])
1505+ curves ["sm" ], curveloop , _ = slicesurf (
1506+ node , face , initpoints [[0 , 1 , 4 ], :], full = True
1507+ )
1508+ curves ["sm" ] = curves ["sm" ][maxloop (curveloop ) - 1 , :]
1509+
14621510 slen , curves ["sm" ], _ = polylinelen (
14631511 curves ["sm" ], initpoints [0 , :], initpoints [1 , :], initpoints [4 , :]
14641512 )
@@ -1475,6 +1523,8 @@ def brain1020(
14751523 landmarks ["cm" ][0 , :],
14761524 landmarks ["sm" ][- 1 , :],
14771525 perc2 * 2 ,
1526+ 0 ,
1527+ maxloop = 1 ,
14781528 )
14791529
14801530 # Step 4: fpz, t8 and oz to determine right 10% axial reference curve
@@ -1485,6 +1535,8 @@ def brain1020(
14851535 landmarks ["cm" ][- 1 , :],
14861536 landmarks ["sm" ][- 1 , :],
14871537 perc2 * 2 ,
1538+ 0 ,
1539+ maxloop = 1 ,
14881540 )
14891541
14901542 # Show plots of the landmarks
@@ -1611,6 +1663,8 @@ def brain1020(
16111663 landmarks ["sm" ][idxcz - 1 - i , :],
16121664 landmarks ["aar" ][i - 1 , :],
16131665 step ,
1666+ 0 ,
1667+ maxloop = 1 ,
16141668 )
16151669
16161670 landmarks [f"cal_{ i } " ] = cal_landmarks
@@ -1661,6 +1715,8 @@ def brain1020(
16611715 landmarks ["sm" ][idxcz - 1 + i , :],
16621716 landmarks ["apr" ][i - 1 , :],
16631717 step ,
1718+ 0 ,
1719+ maxloop = 1 ,
16641720 )
16651721
16661722 landmarks [f"cpl_{ i } " ] = cpl_landmarks
@@ -1696,15 +1752,29 @@ def brain1020(
16961752 landmarks ["papl" ],
16971753 curves ["papl" ],
16981754 ) = slicesurf3 (
1699- node , face , landmarks ["nz" ], landmarks ["lpa" ], landmarks ["iz" ], perc2 * 2
1755+ node ,
1756+ face ,
1757+ landmarks ["nz" ],
1758+ landmarks ["lpa" ],
1759+ landmarks ["iz" ],
1760+ perc2 * 2 ,
1761+ 0 ,
1762+ maxloop = 1 ,
17001763 )
17011764 (
17021765 landmarks ["paar" ],
17031766 curves ["paar" ],
17041767 landmarks ["papr" ],
17051768 curves ["papr" ],
17061769 ) = slicesurf3 (
1707- node , face , landmarks ["nz" ], landmarks ["rpa" ], landmarks ["iz" ], perc2 * 2
1770+ node ,
1771+ face ,
1772+ landmarks ["nz" ],
1773+ landmarks ["rpa" ],
1774+ landmarks ["iz" ],
1775+ perc2 * 2 ,
1776+ 0 ,
1777+ maxloop = 1 ,
17081778 )
17091779
17101780 if showplot :
0 commit comments