[{"data":1,"prerenderedAt":2086},["ShallowReactive",2],{"navigation-docsPy":3,"lib-picker-navigation":161,"docsPy-\u002Fpy\u002Fexamples\u002Farrangements":435,"docsPy-\u002Fpy\u002Fexamples\u002Farrangements-surround":2081},[4],{"title":5,"path":6,"stem":7,"children":8,"page":27},"Py","\u002Fpy","py",[9,28,86,93,115,142],{"title":10,"path":11,"stem":12,"children":13,"icon":27},"Getting Started","\u002Fpy\u002Fgetting-started","py\u002F1.getting-started\u002F1.index",[14,17,22],{"title":15,"path":11,"stem":12,"icon":16},"Introduction","i-lucide-house",{"title":18,"path":19,"stem":20,"icon":21},"Installation","\u002Fpy\u002Fgetting-started\u002Finstallation","py\u002F1.getting-started\u002F2.installation","i-lucide-download",{"title":23,"path":24,"stem":25,"icon":26},"Live Examples","\u002Fpy\u002Fgetting-started\u002Flive-examples","py\u002F1.getting-started\u002F3.live-examples","i-lucide-play",false,{"title":29,"path":30,"stem":31,"children":32,"icon":27},"Modules","\u002Fpy\u002Fmodules","py\u002F2.modules\u002F00.index",[33,36,41,46,51,56,61,66,71,76,81],{"title":34,"path":30,"stem":31,"icon":35},"Overview","i-lucide-library",{"title":37,"path":38,"stem":39,"icon":40},"Core","\u002Fpy\u002Fmodules\u002Fcore","py\u002F2.modules\u002F01.core","i-lucide-atom",{"title":42,"path":43,"stem":44,"icon":45},"Spatial","\u002Fpy\u002Fmodules\u002Fspatial","py\u002F2.modules\u002F02.spatial","i-lucide-scale-3d",{"title":47,"path":48,"stem":49,"icon":50},"Topology","\u002Fpy\u002Fmodules\u002Ftopology","py\u002F2.modules\u002F03.topology","i-lucide-git-graph",{"title":52,"path":53,"stem":54,"icon":55},"Geometry","\u002Fpy\u002Fmodules\u002Fgeometry","py\u002F2.modules\u002F04.geometry","i-lucide-ruler",{"title":57,"path":58,"stem":59,"icon":60},"Remesh","\u002Fpy\u002Fmodules\u002Fremesh","py\u002F2.modules\u002F05.remesh","i-lucide-triangle",{"title":62,"path":63,"stem":64,"icon":65},"Intersect","\u002Fpy\u002Fmodules\u002Fintersect","py\u002F2.modules\u002F06.intersect","i-lucide-squares-intersect",{"title":67,"path":68,"stem":69,"icon":70},"Cut","\u002Fpy\u002Fmodules\u002Fcut","py\u002F2.modules\u002F07.cut","i-lucide-scissors",{"title":72,"path":73,"stem":74,"icon":75},"Clean","\u002Fpy\u002Fmodules\u002Fclean","py\u002F2.modules\u002F08.clean","i-lucide-sparkles",{"title":77,"path":78,"stem":79,"icon":80},"Reindex","\u002Fpy\u002Fmodules\u002Freindex","py\u002F2.modules\u002F09.reidx","i-lucide-shuffle",{"title":82,"path":83,"stem":84,"icon":85},"I\u002FO","\u002Fpy\u002Fmodules\u002Fio","py\u002F2.modules\u002F10.io","i-lucide-file-input",{"title":87,"path":88,"stem":89,"children":90,"icon":27},"Benchmarks","\u002Fpy\u002Fbenchmarks","py\u002F3.benchmarks\u002F1.index",[91],{"title":34,"path":88,"stem":89,"icon":92},"i-lucide-chart-bar-stacked",{"title":94,"path":95,"stem":96,"children":97,"icon":27},"Blender","\u002Fpy\u002Fblender","py\u002F4.blender\u002F1.index",[98,100,105,110],{"title":34,"path":95,"stem":96,"icon":99},"i-vscode-icons:file-type-blender",{"title":101,"path":102,"stem":103,"icon":104},"Convert","\u002Fpy\u002Fblender\u002Fconvert","py\u002F4.blender\u002F2.convert","i-lucide-repeat",{"title":106,"path":107,"stem":108,"icon":109},"Scene","\u002Fpy\u002Fblender\u002Fscene","py\u002F4.blender\u002F3.scene","i-lucide-layers",{"title":111,"path":112,"stem":113,"icon":114},"Plugin Architecture","\u002Fpy\u002Fblender\u002Fplugin","py\u002F4.blender\u002F4.plugin","i-lucide-puzzle",{"title":116,"path":117,"stem":118,"children":119,"icon":27},"Examples","\u002Fpy\u002Fexamples","py\u002F5.examples\u002F0.index",[120,122,127,132,137],{"title":34,"path":117,"stem":118,"icon":121},"i-lucide-book-open",{"title":123,"path":124,"stem":125,"icon":126},"Core Functionality","\u002Fpy\u002Fexamples\u002Fcore-functionality","py\u002F5.examples\u002F2.core-functionality","i-lucide-code",{"title":128,"path":129,"stem":130,"icon":131},"Arrangements and Volumes","\u002Fpy\u002Fexamples\u002Farrangements","py\u002F5.examples\u002F3.arrangements","i-lucide-layers-3",{"title":133,"path":134,"stem":135,"icon":136},"VTK Integration","\u002Fpy\u002Fexamples\u002Fvtk-integration","py\u002F5.examples\u002F4.vtk-integration","i-lucide-grid-2x2",{"title":138,"path":139,"stem":140,"icon":141},"Raycast Rendering","\u002Fpy\u002Fexamples\u002Fraycast-rendering","py\u002F5.examples\u002F5.raycast-rendering","i-lucide-scan-line",{"title":143,"path":144,"stem":145,"children":146,"page":27},"About","\u002Fpy\u002Fabout","py\u002F6.about",[147,151,156],{"title":148,"path":149,"stem":150,"icon":121},"Research","\u002Fpy\u002Fabout\u002Fresearch","py\u002F6.about\u002F1.research",{"title":152,"path":153,"stem":154,"icon":155},"Contributing","\u002Fpy\u002Fabout\u002Fcontributing","py\u002F6.about\u002F2.contributing","i-lucide-heart-handshake",{"title":157,"path":158,"stem":159,"icon":160},"License","\u002Fpy\u002Fabout\u002Flicense","py\u002F6.about\u002F3.license","i-lucide-file-text",{"cpp":162,"py":306,"ts":348},[163],{"title":164,"path":165,"stem":166,"children":167,"page":27},"Cpp","\u002Fcpp","cpp",[168,179,219,245,267,293],{"title":10,"path":169,"stem":170,"children":171,"icon":27},"\u002Fcpp\u002Fgetting-started","cpp\u002F1.getting-started\u002F1.index",[172,173,176],{"title":15,"path":169,"stem":170,"icon":16},{"title":18,"path":174,"stem":175,"icon":21},"\u002Fcpp\u002Fgetting-started\u002Finstallation","cpp\u002F1.getting-started\u002F2.installation",{"title":23,"path":177,"stem":178,"icon":26},"\u002Fcpp\u002Fgetting-started\u002Flive-examples","cpp\u002F1.getting-started\u002F3.live-examples",{"title":29,"path":180,"stem":181,"children":182,"icon":27},"\u002Fcpp\u002Fmodules","cpp\u002F2.modules\u002F00.index",[183,184,187,190,193,196,199,202,205,210,213,216],{"title":34,"path":180,"stem":181,"icon":35},{"title":37,"path":185,"stem":186,"icon":40},"\u002Fcpp\u002Fmodules\u002Fcore","cpp\u002F2.modules\u002F01.core",{"title":42,"path":188,"stem":189,"icon":45},"\u002Fcpp\u002Fmodules\u002Fspatial","cpp\u002F2.modules\u002F02.spatial",{"title":47,"path":191,"stem":192,"icon":50},"\u002Fcpp\u002Fmodules\u002Ftopology","cpp\u002F2.modules\u002F03.topology",{"title":52,"path":194,"stem":195,"icon":55},"\u002Fcpp\u002Fmodules\u002Fgeometry","cpp\u002F2.modules\u002F04.geometry",{"title":57,"path":197,"stem":198,"icon":60},"\u002Fcpp\u002Fmodules\u002Fremesh","cpp\u002F2.modules\u002F05.remesh",{"title":62,"path":200,"stem":201,"icon":65},"\u002Fcpp\u002Fmodules\u002Fintersect","cpp\u002F2.modules\u002F06.intersect",{"title":67,"path":203,"stem":204,"icon":70},"\u002Fcpp\u002Fmodules\u002Fcut","cpp\u002F2.modules\u002F07.cut",{"title":206,"path":207,"stem":208,"icon":209},"CSG","\u002Fcpp\u002Fmodules\u002Fcsg","cpp\u002F2.modules\u002F08.csg","i-lucide-shapes",{"title":72,"path":211,"stem":212,"icon":75},"\u002Fcpp\u002Fmodules\u002Fclean","cpp\u002F2.modules\u002F09.clean",{"title":77,"path":214,"stem":215,"icon":80},"\u002Fcpp\u002Fmodules\u002Freindex","cpp\u002F2.modules\u002F10.reidx",{"title":82,"path":217,"stem":218,"icon":85},"\u002Fcpp\u002Fmodules\u002Fio","cpp\u002F2.modules\u002F11.io",{"title":87,"path":220,"stem":221,"children":222,"icon":27},"\u002Fcpp\u002Fbenchmarks","cpp\u002F3.benchmarks\u002F1.index",[223,224,227,230,233,236,239,242],{"title":34,"path":220,"stem":221,"icon":92},{"title":42,"path":225,"stem":226,"icon":45},"\u002Fcpp\u002Fbenchmarks\u002Fspatial","cpp\u002F3.benchmarks\u002F2.spatial",{"title":47,"path":228,"stem":229,"icon":50},"\u002Fcpp\u002Fbenchmarks\u002Ftopology","cpp\u002F3.benchmarks\u002F3.topology",{"title":52,"path":231,"stem":232,"icon":55},"\u002Fcpp\u002Fbenchmarks\u002Fgeometry","cpp\u002F3.benchmarks\u002F4.geometry",{"title":57,"path":234,"stem":235,"icon":60},"\u002Fcpp\u002Fbenchmarks\u002Fremesh","cpp\u002F3.benchmarks\u002F5.remesh",{"title":62,"path":237,"stem":238,"icon":65},"\u002Fcpp\u002Fbenchmarks\u002Fintersect","cpp\u002F3.benchmarks\u002F6.intersect",{"title":67,"path":240,"stem":241,"icon":70},"\u002Fcpp\u002Fbenchmarks\u002Fcut","cpp\u002F3.benchmarks\u002F7.cut",{"title":82,"path":243,"stem":244,"icon":85},"\u002Fcpp\u002Fbenchmarks\u002Fio","cpp\u002F3.benchmarks\u002F8.io",{"title":246,"path":247,"stem":248,"children":249,"icon":27},"VTK","\u002Fcpp\u002Fvtk","cpp\u002F4.vtk\u002F1.index",[250,251,254,259,264],{"title":34,"path":247,"stem":248,"icon":109},{"title":37,"path":252,"stem":253,"icon":40},"\u002Fcpp\u002Fvtk\u002Fcore","cpp\u002F4.vtk\u002F2.core",{"title":255,"path":256,"stem":257,"icon":258},"Functions","\u002Fcpp\u002Fvtk\u002Ffunctions","cpp\u002F4.vtk\u002F3.functions","i-lucide-function-square",{"title":260,"path":261,"stem":262,"icon":263},"Filters","\u002Fcpp\u002Fvtk\u002Ffilters","cpp\u002F4.vtk\u002F4.filters","i-lucide-filter",{"title":116,"path":265,"stem":266,"icon":26},"\u002Fcpp\u002Fvtk\u002Fexamples","cpp\u002F4.vtk\u002F5.examples",{"title":116,"path":268,"stem":269,"children":270,"icon":27},"\u002Fcpp\u002Fexamples","cpp\u002F5.examples\u002F0.index",[271,272,277,282,285,288],{"title":34,"path":268,"stem":269,"icon":121},{"title":273,"path":274,"stem":275,"icon":276},"Geometry Walkthrough","\u002Fcpp\u002Fexamples\u002Fmesh-assembly","cpp\u002F5.examples\u002F1.mesh-assembly","i-lucide-box",{"title":278,"path":279,"stem":280,"icon":281},"Point Cloud Alignment","\u002Fcpp\u002Fexamples\u002Falignment","cpp\u002F5.examples\u002F2.alignment","i-lucide-move",{"title":128,"path":283,"stem":284,"icon":131},"\u002Fcpp\u002Fexamples\u002Farrangements","cpp\u002F5.examples\u002F3.arrangements",{"title":133,"path":286,"stem":287,"icon":109},"\u002Fcpp\u002Fexamples\u002Fvtk","cpp\u002F5.examples\u002F4.vtk",{"title":289,"path":290,"stem":291,"icon":292},"Coming from Other Libraries","\u002Fcpp\u002Fexamples\u002Flibrary-comparisons","cpp\u002F5.examples\u002F5.library-comparisons","i-lucide-git-compare",{"title":143,"path":294,"stem":295,"children":296,"page":27},"\u002Fcpp\u002Fabout","cpp\u002F6.about",[297,300,303],{"title":148,"path":298,"stem":299,"icon":121},"\u002Fcpp\u002Fabout\u002Fresearch","cpp\u002F6.about\u002F1.research",{"title":152,"path":301,"stem":302,"icon":155},"\u002Fcpp\u002Fabout\u002Fcontributing","cpp\u002F6.about\u002F2.contributing",{"title":157,"path":304,"stem":305,"icon":160},"\u002Fcpp\u002Fabout\u002Flicense","cpp\u002F6.about\u002F3.license",[307],{"title":5,"path":6,"stem":7,"children":308,"page":27},[309,314,327,330,336,343],{"title":10,"path":11,"stem":12,"children":310,"icon":27},[311,312,313],{"title":15,"path":11,"stem":12,"icon":16},{"title":18,"path":19,"stem":20,"icon":21},{"title":23,"path":24,"stem":25,"icon":26},{"title":29,"path":30,"stem":31,"children":315,"icon":27},[316,317,318,319,320,321,322,323,324,325,326],{"title":34,"path":30,"stem":31,"icon":35},{"title":37,"path":38,"stem":39,"icon":40},{"title":42,"path":43,"stem":44,"icon":45},{"title":47,"path":48,"stem":49,"icon":50},{"title":52,"path":53,"stem":54,"icon":55},{"title":57,"path":58,"stem":59,"icon":60},{"title":62,"path":63,"stem":64,"icon":65},{"title":67,"path":68,"stem":69,"icon":70},{"title":72,"path":73,"stem":74,"icon":75},{"title":77,"path":78,"stem":79,"icon":80},{"title":82,"path":83,"stem":84,"icon":85},{"title":87,"path":88,"stem":89,"children":328,"icon":27},[329],{"title":34,"path":88,"stem":89,"icon":92},{"title":94,"path":95,"stem":96,"children":331,"icon":27},[332,333,334,335],{"title":34,"path":95,"stem":96,"icon":99},{"title":101,"path":102,"stem":103,"icon":104},{"title":106,"path":107,"stem":108,"icon":109},{"title":111,"path":112,"stem":113,"icon":114},{"title":116,"path":117,"stem":118,"children":337,"icon":27},[338,339,340,341,342],{"title":34,"path":117,"stem":118,"icon":121},{"title":123,"path":124,"stem":125,"icon":126},{"title":128,"path":129,"stem":130,"icon":131},{"title":133,"path":134,"stem":135,"icon":136},{"title":138,"path":139,"stem":140,"icon":141},{"title":143,"path":144,"stem":145,"children":344,"page":27},[345,346,347],{"title":148,"path":149,"stem":150,"icon":121},{"title":152,"path":153,"stem":154,"icon":155},{"title":157,"path":158,"stem":159,"icon":160},[349],{"title":350,"path":351,"stem":352,"children":353,"page":27},"Ts","\u002Fts","ts",[354,365,400,405,422],{"title":10,"path":355,"stem":356,"children":357,"icon":27},"\u002Fts\u002Fgetting-started","ts\u002F1.getting-started\u002F1.index",[358,359,362],{"title":15,"path":355,"stem":356,"icon":16},{"title":18,"path":360,"stem":361,"icon":21},"\u002Fts\u002Fgetting-started\u002Finstallation","ts\u002F1.getting-started\u002F2.installation",{"title":23,"path":363,"stem":364,"icon":26},"\u002Fts\u002Fgetting-started\u002Flive-examples","ts\u002F1.getting-started\u002F3.live-examples",{"title":29,"path":366,"stem":367,"children":368,"icon":27},"\u002Fts\u002Fmodules","ts\u002F2.modules\u002F00.index",[369,370,373,376,379,382,385,388,391,394,397],{"title":34,"path":366,"stem":367,"icon":35},{"title":37,"path":371,"stem":372,"icon":40},"\u002Fts\u002Fmodules\u002Fcore","ts\u002F2.modules\u002F01.core",{"title":42,"path":374,"stem":375,"icon":45},"\u002Fts\u002Fmodules\u002Fspatial","ts\u002F2.modules\u002F02.spatial",{"title":47,"path":377,"stem":378,"icon":50},"\u002Fts\u002Fmodules\u002Ftopology","ts\u002F2.modules\u002F03.topology",{"title":52,"path":380,"stem":381,"icon":55},"\u002Fts\u002Fmodules\u002Fgeometry","ts\u002F2.modules\u002F04.geometry",{"title":57,"path":383,"stem":384,"icon":60},"\u002Fts\u002Fmodules\u002Fremesh","ts\u002F2.modules\u002F05.remesh",{"title":62,"path":386,"stem":387,"icon":65},"\u002Fts\u002Fmodules\u002Fintersect","ts\u002F2.modules\u002F06.intersect",{"title":67,"path":389,"stem":390,"icon":70},"\u002Fts\u002Fmodules\u002Fcut","ts\u002F2.modules\u002F07.cut",{"title":72,"path":392,"stem":393,"icon":75},"\u002Fts\u002Fmodules\u002Fclean","ts\u002F2.modules\u002F08.clean",{"title":77,"path":395,"stem":396,"icon":80},"\u002Fts\u002Fmodules\u002Freindex","ts\u002F2.modules\u002F09.reidx",{"title":82,"path":398,"stem":399,"icon":85},"\u002Fts\u002Fmodules\u002Fio","ts\u002F2.modules\u002F10.io",{"title":87,"path":401,"stem":402,"children":403,"icon":27},"\u002Fts\u002Fbenchmarks","ts\u002F3.benchmarks\u002F1.index",[404],{"title":34,"path":401,"stem":402,"icon":92},{"title":116,"path":406,"stem":407,"children":408,"icon":27},"\u002Fts\u002Fexamples","ts\u002F4.examples\u002F0.index",[409,410,413,418],{"title":34,"path":406,"stem":407,"icon":121},{"title":123,"path":411,"stem":412,"icon":126},"\u002Fts\u002Fexamples\u002Fcore-functionality","ts\u002F4.examples\u002F2.core-functionality",{"title":414,"path":415,"stem":416,"icon":417},"Alignment","\u002Fts\u002Fexamples\u002Falignment","ts\u002F4.examples\u002F3.alignment","i-lucide-move-3d",{"title":138,"path":419,"stem":420,"icon":421},"\u002Fts\u002Fexamples\u002Fraycast-render","ts\u002F4.examples\u002F4.raycast-render","i-lucide-image",{"title":143,"icon":27,"path":423,"stem":424,"children":425,"page":27},"\u002Fts\u002Fabout","ts\u002F5.about",[426,429,432],{"title":148,"path":427,"stem":428,"icon":121},"\u002Fts\u002Fabout\u002Fresearch","ts\u002F5.about\u002F1.research",{"title":152,"path":430,"stem":431,"icon":155},"\u002Fts\u002Fabout\u002Fcontributing","ts\u002F5.about\u002F2.contributing",{"title":157,"path":433,"stem":434,"icon":160},"\u002Fts\u002Fabout\u002Flicense","ts\u002F5.about\u002F3.license",{"id":436,"title":128,"body":437,"description":2074,"extension":2075,"links":2076,"meta":2077,"navigation":2078,"path":129,"seo":2079,"stem":130,"__hash__":2080},"docsPy\u002Fpy\u002F5.examples\u002F3.arrangements.md",{"type":438,"value":439,"toc":2062},"minimark",[440,444,458,463,466,481,485,488,785,792,796,857,860,898,905,909,935,1044,1060,1071,1075,1123,1126,1166,1176,1204,1207,1211,1252,1269,1275,1279,1292,1435,1438,1465,1471,1475,1483,1564,1568,1885,1902,1905,1913,1916,1920,2035,2058],[441,442,443],"p",{},"This walkthrough takes a small CSG-flavoured scene — two overlapping cubes and a bisecting plane — and pushes it through trueform's arrangement pipeline. The result is a set of closed, manifold, outward-oriented volumes, each labelled by which signed side of the plane it sits on.",[441,445,446,450,451],{},[447,448,449],"strong",{},"Source:"," ",[452,453,457],"a",{"href":454,"rel":455},"https:\u002F\u002Fgithub.com\u002Fpolydera\u002Ftrueform\u002Fblob\u002Fmain\u002Fpython\u002Fexamples\u002Farrangements.py",[456],"nofollow","arrangements.py",[459,460,462],"h2",{"id":461},"what-the-pipeline-does","What the pipeline does",[464,465],"py-arrangements-pipeline-diagram",{},[441,467,468,472,473,476,477,480],{},[469,470,471],"code",{},"tf.mesh_arrangements"," splits every face at every intersection and merges everything into one mesh, tagging each face with its source operand. ",[469,474,475],{},"tf.domain_labels"," then partitions space into bounded volumetric regions (\"domains\"). ",[469,478,479],{},"tf.split_into_domains"," finally emits one watertight outward-oriented submesh per domain. We add a small post-step that reads the slot convention on knife faces to label which volumes are above vs below the knife.",[459,482,484],{"id":483},"building-the-scene","Building the scene",[441,486,487],{},"Two unit cubes offset along the x-axis so they overlap in the middle, and a 4×4 plane on z=0:",[489,490,495],"pre",{"className":491,"code":492,"language":493,"meta":494,"style":494},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import numpy as np\nimport trueform as tf\n\ncube_faces, cube_points = tf.make_box_mesh(2.0, 2.0, 2.0)\nplane_faces, plane_points = tf.make_plane_mesh(4.0, 4.0)\n\ncube0 = tf.Mesh(cube_faces.copy(), cube_points + np.array([-0.5, 0, 0], dtype=cube_points.dtype))\ncube1 = tf.Mesh(cube_faces.copy(), cube_points + np.array([+0.5, 0, 0], dtype=cube_points.dtype))\nknife = tf.Mesh(plane_faces, plane_points)   # tag 2\n","python","",[469,496,497,516,529,536,581,613,618,694,755],{"__ignoreMap":494},[498,499,502,506,510,513],"span",{"class":500,"line":501},"line",1,[498,503,505],{"class":504},"s7zQu","import",[498,507,509],{"class":508},"sTEyZ"," numpy ",[498,511,512],{"class":504},"as",[498,514,515],{"class":508}," np\n",[498,517,519,521,524,526],{"class":500,"line":518},2,[498,520,505],{"class":504},[498,522,523],{"class":508}," trueform ",[498,525,512],{"class":504},[498,527,528],{"class":508}," tf\n",[498,530,532],{"class":500,"line":531},3,[498,533,535],{"emptyLinePlaceholder":534},true,"\n",[498,537,539,542,546,549,552,555,558,562,565,569,571,574,576,578],{"class":500,"line":538},4,[498,540,541],{"class":508},"cube_faces",[498,543,545],{"class":544},"sMK4o",",",[498,547,548],{"class":508}," cube_points ",[498,550,551],{"class":544},"=",[498,553,554],{"class":508}," tf",[498,556,557],{"class":544},".",[498,559,561],{"class":560},"s2Zo4","make_box_mesh",[498,563,564],{"class":544},"(",[498,566,568],{"class":567},"sbssI","2.0",[498,570,545],{"class":544},[498,572,573],{"class":567}," 2.0",[498,575,545],{"class":544},[498,577,573],{"class":567},[498,579,580],{"class":544},")\n",[498,582,584,587,589,592,594,596,598,601,603,606,608,611],{"class":500,"line":583},5,[498,585,586],{"class":508},"plane_faces",[498,588,545],{"class":544},[498,590,591],{"class":508}," plane_points ",[498,593,551],{"class":544},[498,595,554],{"class":508},[498,597,557],{"class":544},[498,599,600],{"class":560},"make_plane_mesh",[498,602,564],{"class":544},[498,604,605],{"class":567},"4.0",[498,607,545],{"class":544},[498,609,610],{"class":567}," 4.0",[498,612,580],{"class":544},[498,614,616],{"class":500,"line":615},6,[498,617,535],{"emptyLinePlaceholder":534},[498,619,621,624,626,628,630,633,635,637,639,642,645,647,650,653,655,658,661,664,666,669,671,673,676,680,682,685,687,691],{"class":500,"line":620},7,[498,622,623],{"class":508},"cube0 ",[498,625,551],{"class":544},[498,627,554],{"class":508},[498,629,557],{"class":544},[498,631,632],{"class":560},"Mesh",[498,634,564],{"class":544},[498,636,541],{"class":560},[498,638,557],{"class":544},[498,640,641],{"class":560},"copy",[498,643,644],{"class":544},"(),",[498,646,548],{"class":560},[498,648,649],{"class":544},"+",[498,651,652],{"class":560}," np",[498,654,557],{"class":544},[498,656,657],{"class":560},"array",[498,659,660],{"class":544},"([-",[498,662,663],{"class":567},"0.5",[498,665,545],{"class":544},[498,667,668],{"class":567}," 0",[498,670,545],{"class":544},[498,672,668],{"class":567},[498,674,675],{"class":544},"],",[498,677,679],{"class":678},"sHdIc"," dtype",[498,681,551],{"class":544},[498,683,684],{"class":560},"cube_points",[498,686,557],{"class":544},[498,688,690],{"class":689},"swJcz","dtype",[498,692,693],{"class":544},"))\n",[498,695,697,700,702,704,706,708,710,712,714,716,718,720,722,724,726,728,731,733,735,737,739,741,743,745,747,749,751,753],{"class":500,"line":696},8,[498,698,699],{"class":508},"cube1 ",[498,701,551],{"class":544},[498,703,554],{"class":508},[498,705,557],{"class":544},[498,707,632],{"class":560},[498,709,564],{"class":544},[498,711,541],{"class":560},[498,713,557],{"class":544},[498,715,641],{"class":560},[498,717,644],{"class":544},[498,719,548],{"class":560},[498,721,649],{"class":544},[498,723,652],{"class":560},[498,725,557],{"class":544},[498,727,657],{"class":560},[498,729,730],{"class":544},"([+",[498,732,663],{"class":567},[498,734,545],{"class":544},[498,736,668],{"class":567},[498,738,545],{"class":544},[498,740,668],{"class":567},[498,742,675],{"class":544},[498,744,679],{"class":678},[498,746,551],{"class":544},[498,748,684],{"class":560},[498,750,557],{"class":544},[498,752,690],{"class":689},[498,754,693],{"class":544},[498,756,758,761,763,765,767,769,771,773,775,778,781],{"class":500,"line":757},9,[498,759,760],{"class":508},"knife ",[498,762,551],{"class":544},[498,764,554],{"class":508},[498,766,557],{"class":544},[498,768,632],{"class":560},[498,770,564],{"class":544},[498,772,586],{"class":560},[498,774,545],{"class":544},[498,776,777],{"class":560}," plane_points",[498,779,780],{"class":544},")",[498,782,784],{"class":783},"sHwdD","   # tag 2\n",[441,786,787,788,791],{},"The two cubes alone produce three bounded regions (cube0-only, intersection, cube1-only). The plane bisects all three, so we expect ",[447,789,790],{},"six"," bounded domains.",[459,793,795],{"id":794},"building-the-arrangement","Building the arrangement",[489,797,799],{"className":491,"code":798,"language":493,"meta":494,"style":494},"(arr_faces, arr_points), tag_labels, face_labels = tf.mesh_arrangements(\n    [cube0, cube1, knife])\n",[469,800,801,836],{"__ignoreMap":494},[498,802,803,805,808,810,813,816,819,821,824,826,828,830,833],{"class":500,"line":501},[498,804,564],{"class":544},[498,806,807],{"class":508},"arr_faces",[498,809,545],{"class":544},[498,811,812],{"class":508}," arr_points",[498,814,815],{"class":544},"),",[498,817,818],{"class":508}," tag_labels",[498,820,545],{"class":544},[498,822,823],{"class":508}," face_labels ",[498,825,551],{"class":544},[498,827,554],{"class":508},[498,829,557],{"class":544},[498,831,832],{"class":560},"mesh_arrangements",[498,834,835],{"class":544},"(\n",[498,837,838,841,844,846,849,851,854],{"class":500,"line":518},[498,839,840],{"class":544},"    [",[498,842,843],{"class":560},"cube0",[498,845,545],{"class":544},[498,847,848],{"class":560}," cube1",[498,850,545],{"class":544},[498,852,853],{"class":560}," knife",[498,855,856],{"class":544},"])\n",[441,858,859],{},"The return is three pieces:",[861,862,863,870,892],"ul",{},[864,865,866,869],"li",{},[469,867,868],{},"(arr_faces, arr_points)"," — the merged triangle mesh with all intersections resolved.",[864,871,872,875,876,879,880,883,884,887,888,891],{},[469,873,874],{},"tag_labels[f]"," — which input operand face ",[469,877,878],{},"f"," came from (",[469,881,882],{},"0",", ",[469,885,886],{},"1",", or ",[469,889,890],{},"2"," here).",[864,893,894,897],{},[469,895,896],{},"face_labels[f]"," — which face within that operand it came from.",[441,899,900,901,904],{},"For our scene this produces ",[447,902,903],{},"176 faces, 48 points"," before cleaning.",[459,906,908],{"id":907},"cleaning-and-reindexing-tags","Cleaning and reindexing tags",[441,910,911,914,915,918,919,922,923,926,927,930,931,934],{},[469,912,913],{},"tf.cleaned"," does three things in one pass: it ",[447,916,917],{},"merges coincident vertices"," within a tolerance, ",[447,920,921],{},"drops topologically degenerate triangles"," (faces that collapse to a point or edge after merging), and ",[447,924,925],{},"removes duplicate triangles",". With ",[469,928,929],{},"return_index_map=True"," it also returns index maps describing exactly what happened to each face and point, so per-face attributes like ",[469,932,933],{},"tag_labels"," can be reindexed through them to stay aligned with the cleaned mesh:",[489,936,938],{"className":491,"code":937,"language":493,"meta":494,"style":494},"(arr_faces, arr_points), (face_f, kept_faces), _ = tf.cleaned(\n    (arr_faces, arr_points), 1e-6, return_index_map=True)\ntag_labels = tag_labels[kept_faces]\narr = tf.Mesh(arr_faces, arr_points)\n",[469,939,940,979,1003,1021],{"__ignoreMap":494},[498,941,942,944,946,948,950,952,955,958,960,963,965,968,970,972,974,977],{"class":500,"line":501},[498,943,564],{"class":544},[498,945,807],{"class":508},[498,947,545],{"class":544},[498,949,812],{"class":508},[498,951,815],{"class":544},[498,953,954],{"class":544}," (",[498,956,957],{"class":508},"face_f",[498,959,545],{"class":544},[498,961,962],{"class":508}," kept_faces",[498,964,815],{"class":544},[498,966,967],{"class":508}," _ ",[498,969,551],{"class":544},[498,971,554],{"class":508},[498,973,557],{"class":544},[498,975,976],{"class":560},"cleaned",[498,978,835],{"class":544},[498,980,981,984,986,988,990,992,995,997,1000],{"class":500,"line":518},[498,982,983],{"class":544},"    (",[498,985,807],{"class":560},[498,987,545],{"class":544},[498,989,812],{"class":560},[498,991,815],{"class":544},[498,993,994],{"class":567}," 1e-6",[498,996,545],{"class":544},[498,998,999],{"class":678}," return_index_map",[498,1001,1002],{"class":544},"=True)\n",[498,1004,1005,1008,1010,1012,1015,1018],{"class":500,"line":531},[498,1006,1007],{"class":508},"tag_labels ",[498,1009,551],{"class":544},[498,1011,818],{"class":508},[498,1013,1014],{"class":544},"[",[498,1016,1017],{"class":508},"kept_faces",[498,1019,1020],{"class":544},"]\n",[498,1022,1023,1026,1028,1030,1032,1034,1036,1038,1040,1042],{"class":500,"line":538},[498,1024,1025],{"class":508},"arr ",[498,1027,551],{"class":544},[498,1029,554],{"class":508},[498,1031,557],{"class":544},[498,1033,632],{"class":560},[498,1035,564],{"class":544},[498,1037,807],{"class":560},[498,1039,545],{"class":544},[498,1041,812],{"class":560},[498,1043,580],{"class":544},[441,1045,1046,1048,1049,1052,1053,1056,1057,557],{},[469,1047,1017],{}," is a numpy array of the surviving old face ids in new order, so ",[469,1050,1051],{},"tag_labels[kept_faces]"," produces a new array of the right length aligned to the cleaned mesh. In our scene cleaning takes us from 176 → ",[447,1054,1055],{},"114 faces",", 48 → ",[447,1058,1059],{},"40 points",[1061,1062,1064],"tip",{"icon":1063},"i-lucide-info",[441,1065,1066,1067,1070],{},"This reindex pattern applies to any per-face attribute you want to carry through a cleaning step — colours, scalar fields, user IDs. The ",[469,1068,1069],{},"(f, kept_ids)"," index map returned by index-destructive operations is the canonical handle.",[459,1072,1074],{"id":1073},"computing-domain-labels","Computing domain labels",[489,1076,1078],{"className":491,"code":1077,"language":493,"meta":494,"style":494},"labels_2d, n_domains, _ = tf.domain_labels(\n    arr, ignore_open_fragments=True, exclude_outer_shell=True)\n",[469,1079,1080,1105],{"__ignoreMap":494},[498,1081,1082,1085,1087,1090,1092,1094,1096,1098,1100,1103],{"class":500,"line":501},[498,1083,1084],{"class":508},"labels_2d",[498,1086,545],{"class":544},[498,1088,1089],{"class":508}," n_domains",[498,1091,545],{"class":544},[498,1093,967],{"class":508},[498,1095,551],{"class":544},[498,1097,554],{"class":508},[498,1099,557],{"class":544},[498,1101,1102],{"class":560},"domain_labels",[498,1104,835],{"class":544},[498,1106,1107,1110,1112,1115,1118,1121],{"class":500,"line":518},[498,1108,1109],{"class":560},"    arr",[498,1111,545],{"class":544},[498,1113,1114],{"class":678}," ignore_open_fragments",[498,1116,1117],{"class":544},"=True,",[498,1119,1120],{"class":678}," exclude_outer_shell",[498,1122,1002],{"class":544},[441,1124,1125],{},"Two flags shape the output:",[1127,1128,1129,1142],"table",{},[1130,1131,1132],"thead",{},[1133,1134,1135,1139],"tr",{},[1136,1137,1138],"th",{},"Flag",[1136,1140,1141],{},"Effect",[1143,1144,1145,1156],"tbody",{},[1133,1146,1147,1153],{},[1148,1149,1150],"td",{},[469,1151,1152],{},"ignore_open_fragments",[1148,1154,1155],{},"Park face-sides bounding open fragments (in our scene: the plane's outer ring that pokes outside the cube union) at the sentinel label.",[1133,1157,1158,1163],{},[1148,1159,1160],{},[469,1161,1162],{},"exclude_outer_shell",[1148,1164,1165],{},"Fold the unbounded universe domain into the same sentinel.",[441,1167,1168,1169,1172,1173,1175],{},"What survives is the bounded interior. For our scene ",[469,1170,1171],{},"n_domains == 6",". Each face ",[469,1174,878],{}," carries two domain ids:",[861,1177,1178,1194],{},[864,1179,1180,1183,1184,1186,1187,1190,1191,1193],{},[469,1181,1182],{},"labels_2d[f, 0]"," — the domain that contains ",[469,1185,878],{}," with ",[447,1188,1189],{},"reversed winding"," (the side ",[469,1192,878],{},"'s stored normal points INTO).",[864,1195,1196,1183,1199,1186,1201,557],{},[469,1197,1198],{},"labels_2d[f, 1]",[469,1200,878],{},[447,1202,1203],{},"forward winding",[441,1205,1206],{},"That two-slot encoding is what makes the signed-side selection in the next step trivial.",[459,1208,1210],{"id":1209},"extracting-the-volumes","Extracting the volumes",[489,1212,1214],{"className":491,"code":1213,"language":493,"meta":494,"style":494},"volumes, comp_labels = tf.split_into_domains(arr, (labels_2d, n_domains))\n",[469,1215,1216],{"__ignoreMap":494},[498,1217,1218,1221,1223,1226,1228,1230,1232,1235,1237,1240,1242,1244,1246,1248,1250],{"class":500,"line":501},[498,1219,1220],{"class":508},"volumes",[498,1222,545],{"class":544},[498,1224,1225],{"class":508}," comp_labels ",[498,1227,551],{"class":544},[498,1229,554],{"class":508},[498,1231,557],{"class":544},[498,1233,1234],{"class":560},"split_into_domains",[498,1236,564],{"class":544},[498,1238,1239],{"class":560},"arr",[498,1241,545],{"class":544},[498,1243,954],{"class":544},[498,1245,1084],{"class":560},[498,1247,545],{"class":544},[498,1249,1089],{"class":560},[498,1251,693],{"class":544},[441,1253,1254,1257,1258,1261,1262,1265,1266,1268],{},[469,1255,1256],{},"volumes[i]"," is a ",[469,1259,1260],{},"(faces, points)"," tuple — a standalone watertight, manifold, outward-oriented submesh for the domain ",[469,1263,1264],{},"comp_labels[i]",". ",[469,1267,1234],{}," reverses side-0 emissions and keeps side-1 emissions, so each cap face ends up pointing outward of its volume by construction.",[441,1270,1271,1272,557],{},"For our scene: ",[447,1273,1274],{},"6 volumes",[459,1276,1278],{"id":1277},"selecting-volumes-by-signed-side-of-the-knife","Selecting volumes by signed side of the knife",[441,1280,1281,1282,1284,1285,1287,1288,1291],{},"The knife (tag 2) has stored normal +Z. By the slot convention above, ",[469,1283,1182],{}," for an interior knife face is the domain on the +Z side, and ",[469,1286,1198],{}," is on the −Z side. We mask to knife faces, drop sentinel hits, and dedupe with ",[469,1289,1290],{},"np.unique",":",[489,1293,1295],{"className":491,"code":1294,"language":493,"meta":494,"style":494},"knife_mask = tag_labels == 2\nabove = labels_2d[knife_mask, 0]\nbelow = labels_2d[knife_mask, 1]\ninside = (above \u003C n_domains) & (below \u003C n_domains)\nabove_ids = np.unique(above[inside])\nbelow_ids = np.unique(below[inside])\n",[469,1296,1297,1313,1334,1354,1385,1411],{"__ignoreMap":494},[498,1298,1299,1302,1304,1307,1310],{"class":500,"line":501},[498,1300,1301],{"class":508},"knife_mask ",[498,1303,551],{"class":544},[498,1305,1306],{"class":508}," tag_labels ",[498,1308,1309],{"class":544},"==",[498,1311,1312],{"class":567}," 2\n",[498,1314,1315,1318,1320,1323,1325,1328,1330,1332],{"class":500,"line":518},[498,1316,1317],{"class":508},"above ",[498,1319,551],{"class":544},[498,1321,1322],{"class":508}," labels_2d",[498,1324,1014],{"class":544},[498,1326,1327],{"class":508},"knife_mask",[498,1329,545],{"class":544},[498,1331,668],{"class":567},[498,1333,1020],{"class":544},[498,1335,1336,1339,1341,1343,1345,1347,1349,1352],{"class":500,"line":531},[498,1337,1338],{"class":508},"below ",[498,1340,551],{"class":544},[498,1342,1322],{"class":508},[498,1344,1014],{"class":544},[498,1346,1327],{"class":508},[498,1348,545],{"class":544},[498,1350,1351],{"class":567}," 1",[498,1353,1020],{"class":544},[498,1355,1356,1359,1361,1363,1365,1368,1370,1372,1375,1377,1379,1381,1383],{"class":500,"line":538},[498,1357,1358],{"class":508},"inside ",[498,1360,551],{"class":544},[498,1362,954],{"class":544},[498,1364,1317],{"class":508},[498,1366,1367],{"class":544},"\u003C",[498,1369,1089],{"class":508},[498,1371,780],{"class":544},[498,1373,1374],{"class":544}," &",[498,1376,954],{"class":544},[498,1378,1338],{"class":508},[498,1380,1367],{"class":544},[498,1382,1089],{"class":508},[498,1384,580],{"class":544},[498,1386,1387,1390,1392,1394,1396,1399,1401,1404,1406,1409],{"class":500,"line":583},[498,1388,1389],{"class":508},"above_ids ",[498,1391,551],{"class":544},[498,1393,652],{"class":508},[498,1395,557],{"class":544},[498,1397,1398],{"class":560},"unique",[498,1400,564],{"class":544},[498,1402,1403],{"class":560},"above",[498,1405,1014],{"class":544},[498,1407,1408],{"class":560},"inside",[498,1410,856],{"class":544},[498,1412,1413,1416,1418,1420,1422,1424,1426,1429,1431,1433],{"class":500,"line":615},[498,1414,1415],{"class":508},"below_ids ",[498,1417,551],{"class":544},[498,1419,652],{"class":508},[498,1421,557],{"class":544},[498,1423,1398],{"class":560},[498,1425,564],{"class":544},[498,1427,1428],{"class":560},"below",[498,1430,1014],{"class":544},[498,1432,1408],{"class":560},[498,1434,856],{"class":544},[441,1436,1437],{},"A few things worth pulling out:",[861,1439,1440,1449,1458],{},[864,1441,1442,954,1445,1448],{},[447,1443,1444],{},"Boolean masking",[469,1446,1447],{},"tag_labels == 2",") picks out the knife faces in one vectorised step.",[864,1450,1451,954,1454,1457],{},[447,1452,1453],{},"Sentinel skip",[469,1455,1456],{},"\u003C n_domains",") drops the knife faces that landed in the outer ring — those don't bound any real domain.",[864,1459,1460,1464],{},[447,1461,1462],{},[469,1463,1290],{}," handles dedup. The knife can hit several closed regions (here: cube0-only, intersection, cube1-only), so each side ends up with multiple domain ids.",[441,1466,1271,1467,1470],{},[447,1468,1469],{},"3 above, 3 below",". The cube0-only, intersection, and cube1-only volumes each contribute one upper and one lower half.",[459,1472,1474],{"id":1473},"mapping-domain-ids-to-volume-indices","Mapping domain ids to volume indices",[441,1476,1477,1479,1480,1482],{},[469,1478,1264],{}," tells us which domain ",[469,1481,1256],{}," represents. A scatter inverts that in one line:",[489,1484,1486],{"className":491,"code":1485,"language":493,"meta":494,"style":494},"domain_to_idx = np.full(n_domains, -1, dtype=np.int64)\ndomain_to_idx[comp_labels] = np.arange(len(comp_labels))\n",[469,1487,1488,1530],{"__ignoreMap":494},[498,1489,1490,1493,1495,1497,1499,1502,1504,1507,1509,1512,1514,1516,1518,1520,1523,1525,1528],{"class":500,"line":501},[498,1491,1492],{"class":508},"domain_to_idx ",[498,1494,551],{"class":544},[498,1496,652],{"class":508},[498,1498,557],{"class":544},[498,1500,1501],{"class":560},"full",[498,1503,564],{"class":544},[498,1505,1506],{"class":560},"n_domains",[498,1508,545],{"class":544},[498,1510,1511],{"class":544}," -",[498,1513,886],{"class":567},[498,1515,545],{"class":544},[498,1517,679],{"class":678},[498,1519,551],{"class":544},[498,1521,1522],{"class":560},"np",[498,1524,557],{"class":544},[498,1526,1527],{"class":689},"int64",[498,1529,580],{"class":544},[498,1531,1532,1535,1537,1540,1543,1546,1548,1550,1553,1555,1558,1560,1562],{"class":500,"line":518},[498,1533,1534],{"class":508},"domain_to_idx",[498,1536,1014],{"class":544},[498,1538,1539],{"class":508},"comp_labels",[498,1541,1542],{"class":544},"]",[498,1544,1545],{"class":544}," =",[498,1547,652],{"class":508},[498,1549,557],{"class":544},[498,1551,1552],{"class":560},"arange",[498,1554,564],{"class":544},[498,1556,1557],{"class":560},"len",[498,1559,564],{"class":544},[498,1561,1539],{"class":560},[498,1563,693],{"class":544},[459,1565,1567],{"id":1566},"writing-volumes-and-verifying","Writing volumes and verifying",[489,1569,1571],{"className":491,"code":1570,"language":493,"meta":494,"style":494},"def write_side(ids, prefix):\n    for k, d in enumerate(ids):\n        vf, vp = volumes[int(domain_to_idx[d])]\n        m = tf.Mesh(vf, vp)\n        fname = f\"{prefix}_{k}.stl\"\n        tf.write_stl(m, fname)\n        print(f\"  wrote {fname} \"\n              f\"(faces={len(vf)}, \"\n              f\"closed={tf.is_closed(m)}, \"\n              f\"manifold={tf.is_manifold(m)})\")\n\nwrite_side(above_ids, \"above\")\nwrite_side(below_ids, \"below\")\n",[469,1572,1573,1595,1620,1653,1678,1714,1736,1758,1781,1808,1838,1843,1865],{"__ignoreMap":494},[498,1574,1575,1579,1582,1584,1587,1589,1592],{"class":500,"line":501},[498,1576,1578],{"class":1577},"spNyl","def",[498,1580,1581],{"class":560}," write_side",[498,1583,564],{"class":544},[498,1585,1586],{"class":678},"ids",[498,1588,545],{"class":544},[498,1590,1591],{"class":678}," prefix",[498,1593,1594],{"class":544},"):\n",[498,1596,1597,1600,1603,1605,1608,1611,1614,1616,1618],{"class":500,"line":518},[498,1598,1599],{"class":504},"    for",[498,1601,1602],{"class":508}," k",[498,1604,545],{"class":544},[498,1606,1607],{"class":508}," d ",[498,1609,1610],{"class":504},"in",[498,1612,1613],{"class":560}," enumerate",[498,1615,564],{"class":544},[498,1617,1586],{"class":560},[498,1619,1594],{"class":544},[498,1621,1622,1625,1627,1630,1632,1635,1637,1641,1643,1645,1647,1650],{"class":500,"line":531},[498,1623,1624],{"class":508},"        vf",[498,1626,545],{"class":544},[498,1628,1629],{"class":508}," vp ",[498,1631,551],{"class":544},[498,1633,1634],{"class":508}," volumes",[498,1636,1014],{"class":544},[498,1638,1640],{"class":1639},"sBMFI","int",[498,1642,564],{"class":544},[498,1644,1534],{"class":560},[498,1646,1014],{"class":544},[498,1648,1649],{"class":560},"d",[498,1651,1652],{"class":544},"])]\n",[498,1654,1655,1658,1660,1662,1664,1666,1668,1671,1673,1676],{"class":500,"line":538},[498,1656,1657],{"class":508},"        m ",[498,1659,551],{"class":544},[498,1661,554],{"class":508},[498,1663,557],{"class":544},[498,1665,632],{"class":560},[498,1667,564],{"class":544},[498,1669,1670],{"class":560},"vf",[498,1672,545],{"class":544},[498,1674,1675],{"class":560}," vp",[498,1677,580],{"class":544},[498,1679,1680,1683,1685,1688,1692,1695,1698,1701,1704,1706,1709,1711],{"class":500,"line":583},[498,1681,1682],{"class":508},"        fname ",[498,1684,551],{"class":544},[498,1686,1687],{"class":1577}," f",[498,1689,1691],{"class":1690},"sfazB","\"",[498,1693,1694],{"class":567},"{",[498,1696,1697],{"class":508},"prefix",[498,1699,1700],{"class":567},"}",[498,1702,1703],{"class":1690},"_",[498,1705,1694],{"class":567},[498,1707,1708],{"class":508},"k",[498,1710,1700],{"class":567},[498,1712,1713],{"class":1690},".stl\"\n",[498,1715,1716,1719,1721,1724,1726,1729,1731,1734],{"class":500,"line":615},[498,1717,1718],{"class":508},"        tf",[498,1720,557],{"class":544},[498,1722,1723],{"class":560},"write_stl",[498,1725,564],{"class":544},[498,1727,1728],{"class":560},"m",[498,1730,545],{"class":544},[498,1732,1733],{"class":560}," fname",[498,1735,580],{"class":544},[498,1737,1738,1741,1743,1745,1748,1750,1753,1755],{"class":500,"line":620},[498,1739,1740],{"class":560},"        print",[498,1742,564],{"class":544},[498,1744,878],{"class":1577},[498,1746,1747],{"class":1690},"\"  wrote ",[498,1749,1694],{"class":567},[498,1751,1752],{"class":560},"fname",[498,1754,1700],{"class":567},[498,1756,1757],{"class":1690}," \"\n",[498,1759,1760,1763,1766,1768,1770,1772,1774,1776,1778],{"class":500,"line":696},[498,1761,1762],{"class":1577},"              f",[498,1764,1765],{"class":1690},"\"(faces=",[498,1767,1694],{"class":567},[498,1769,1557],{"class":560},[498,1771,564],{"class":544},[498,1773,1670],{"class":560},[498,1775,780],{"class":544},[498,1777,1700],{"class":567},[498,1779,1780],{"class":1690},", \"\n",[498,1782,1783,1785,1788,1790,1793,1795,1798,1800,1802,1804,1806],{"class":500,"line":757},[498,1784,1762],{"class":1577},[498,1786,1787],{"class":1690},"\"closed=",[498,1789,1694],{"class":567},[498,1791,1792],{"class":560},"tf",[498,1794,557],{"class":544},[498,1796,1797],{"class":560},"is_closed",[498,1799,564],{"class":544},[498,1801,1728],{"class":560},[498,1803,780],{"class":544},[498,1805,1700],{"class":567},[498,1807,1780],{"class":1690},[498,1809,1811,1813,1816,1818,1820,1822,1825,1827,1829,1831,1833,1836],{"class":500,"line":1810},10,[498,1812,1762],{"class":1577},[498,1814,1815],{"class":1690},"\"manifold=",[498,1817,1694],{"class":567},[498,1819,1792],{"class":560},[498,1821,557],{"class":544},[498,1823,1824],{"class":560},"is_manifold",[498,1826,564],{"class":544},[498,1828,1728],{"class":560},[498,1830,780],{"class":544},[498,1832,1700],{"class":567},[498,1834,1835],{"class":1690},")\"",[498,1837,580],{"class":544},[498,1839,1841],{"class":500,"line":1840},11,[498,1842,535],{"emptyLinePlaceholder":534},[498,1844,1846,1849,1851,1854,1856,1859,1861,1863],{"class":500,"line":1845},12,[498,1847,1848],{"class":560},"write_side",[498,1850,564],{"class":544},[498,1852,1853],{"class":560},"above_ids",[498,1855,545],{"class":544},[498,1857,1858],{"class":544}," \"",[498,1860,1403],{"class":1690},[498,1862,1691],{"class":544},[498,1864,580],{"class":544},[498,1866,1868,1870,1872,1875,1877,1879,1881,1883],{"class":500,"line":1867},13,[498,1869,1848],{"class":560},[498,1871,564],{"class":544},[498,1873,1874],{"class":560},"below_ids",[498,1876,545],{"class":544},[498,1878,1858],{"class":544},[498,1880,1428],{"class":1690},[498,1882,1691],{"class":544},[498,1884,580],{"class":544},[441,1886,1887,1890,1891,1894,1895,1898,1899,1901],{},[469,1888,1889],{},"tf.is_closed"," checks that every edge is shared by exactly two faces (no boundary), and ",[469,1892,1893],{},"tf.is_manifold"," checks that no edge is shared by three or more. Every output volume should print ",[469,1896,1897],{},"closed=True, manifold=True"," — the structural guarantee ",[469,1900,1234],{}," makes is verified at the boundary.",[441,1903,1904],{},"Running the example writes six STL files and prints:",[489,1906,1911],{"className":1907,"code":1909,"language":1910,"meta":494},[1908],"language-text","=== Arrangement ===\nFaces:  176\nPoints: 48\n\n=== Cleaned ===\nFaces:  114\nPoints: 40\n\n=== Domain labels ===\nBounded domains: 6\nVolumes extracted: 6\n\n=== Signed side of the knife ===\nAbove (+normal): 3 volumes\nBelow (-normal): 3 volumes\n  wrote above_0.stl (faces=22, closed=True, manifold=True)\n  wrote above_1.stl (faces=24, closed=True, manifold=True)\n  wrote above_2.stl (faces=22, closed=True, manifold=True)\n  wrote below_0.stl (faces=24, closed=True, manifold=True)\n  wrote below_1.stl (faces=22, closed=True, manifold=True)\n  wrote below_2.stl (faces=22, closed=True, manifold=True)\n","text",[469,1912,1909],{"__ignoreMap":494},[441,1914,1915],{},"The 24-face volumes are the intersection halves — they pick up parts of both cubes' inner walls, so their boundary surface is slightly larger than the cube-only halves.",[459,1917,1919],{"id":1918},"summary","Summary",[1127,1921,1922,1935],{},[1130,1923,1924],{},[1133,1925,1926,1929,1932],{},[1136,1927,1928],{},"Step",[1136,1930,1931],{},"API",[1136,1933,1934],{},"What you get",[1143,1936,1937,1955,1967,1980,1993,2005,2020],{},[1133,1938,1939,1942,1946],{},[1148,1940,1941],{},"Build arrangement",[1148,1943,1944],{},[469,1945,471],{},[1148,1947,1948,1949,1951,1952],{},"One merged mesh + ",[469,1950,933],{}," + ",[469,1953,1954],{},"face_labels",[1133,1956,1957,1959,1964],{},[1148,1958,72],{},[1148,1960,1961],{},[469,1962,1963],{},"tf.cleaned(..., return_index_map=True)",[1148,1965,1966],{},"Cleaned mesh + face\u002Fpoint index maps",[1133,1968,1969,1972,1977],{},[1148,1970,1971],{},"Reindex attributes",[1148,1973,1974],{},[469,1975,1976],{},"attr[kept_faces]",[1148,1978,1979],{},"Per-face attributes aligned to cleaned mesh",[1133,1981,1982,1985,1990],{},[1148,1983,1984],{},"Label domains",[1148,1986,1987],{},[469,1988,1989],{},"tf.domain_labels(mesh, flags)",[1148,1991,1992],{},"Per-face two-slot domain ids",[1133,1994,1995,1998,2002],{},[1148,1996,1997],{},"Extract volumes",[1148,1999,2000],{},[469,2001,479],{},[1148,2003,2004],{},"Closed, manifold, outward-oriented submeshes",[1133,2006,2007,2010,2017],{},[1148,2008,2009],{},"Side selection",[1148,2011,2012,1951,2015],{},[469,2013,2014],{},"labels_2d[knife, 0\u002F1]",[469,2016,1290],{},[1148,2018,2019],{},"Domain ids on each signed side",[1133,2021,2022,2025,2032],{},[1148,2023,2024],{},"Verify",[1148,2026,2027,2029,2030],{},[469,2028,1889],{}," \u002F ",[469,2031,1893],{},[1148,2033,2034],{},"Structural sanity per output",[1061,2036,2037],{"icon":1063},[441,2038,2039,2040,2042,2043,883,2045,883,2047,2049,2050,2042,2052,2049,2054,2042,2056,557],{},"See ",[452,2041,47],{"href":48}," for ",[469,2044,1102],{},[469,2046,1797],{},[469,2048,1824],{},"; ",[452,2051,77],{"href":78},[469,2053,1234],{},[452,2055,67],{"href":68},[469,2057,832],{},[2059,2060,2061],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}",{"title":494,"searchDepth":501,"depth":518,"links":2063},[2064,2065,2066,2067,2068,2069,2070,2071,2072,2073],{"id":461,"depth":518,"text":462},{"id":483,"depth":518,"text":484},{"id":794,"depth":518,"text":795},{"id":907,"depth":518,"text":908},{"id":1073,"depth":518,"text":1074},{"id":1209,"depth":518,"text":1210},{"id":1277,"depth":518,"text":1278},{"id":1473,"depth":518,"text":1474},{"id":1566,"depth":518,"text":1567},{"id":1918,"depth":518,"text":1919},"Building an arrangement from intersecting meshes, extracting closed bounded volumes, and selecting them by signed side of a knife.","md",null,{},{"icon":131},{"title":128,"description":2074},"2w8r7EtA7Gw3vGS6tOGGbSymMiS3u2yQZ3MZUas-ODM",[2082,2084],{"title":123,"path":124,"stem":125,"description":2083,"icon":126,"children":-1},"Self-contained examples demonstrating primary features of trueform.",{"title":133,"path":134,"stem":135,"description":2085,"icon":136,"children":-1},"Interactive applications demonstrating real-time collision detection, mesh booleans, and curve extraction.",1780947765531]