Skip to content

Commit ff98ad1

Browse files
authored
feat: new hull mesh generation (#214)
* feat: new hull mesh generation * update hull mesh functions * fix: saveSurfaceMesh
1 parent 59e5e31 commit ff98ad1

5 files changed

Lines changed: 73 additions & 59 deletions

File tree

include/viennaps/psDomain.hpp

Lines changed: 48 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <lsExpand.hpp>
1414
#include <lsRemoveStrayPoints.hpp>
1515
#include <lsToDiskMesh.hpp>
16+
#include <lsToHullMesh.hpp>
1617
#include <lsToMesh.hpp>
1718
#include <lsToMultiSurfaceMesh.hpp>
1819
#include <lsToSurfaceMesh.hpp>
@@ -466,34 +467,17 @@ VIENNAPS_TEMPLATE_ND(NumericType, D) class Domain {
466467
return meshes;
467468
}
468469

469-
// Save the level set as a VTK file.
470-
void saveLevelSetMesh(const std::string &fileName, int width = 1) {
471-
auto meshes = getLevelSetMesh(width);
472-
for (int i = 0; i < meshes.size(); i++) {
473-
viennals::VTKWriter<NumericType> writer(
474-
meshes[i], fileName + "_layer" + std::to_string(i) + ".vtp");
475-
writer.setMetaData(metaData_);
476-
writer.apply();
477-
}
478-
}
479-
480470
SmartPointer<viennals::Mesh<NumericType>>
481-
getSurfaceMesh(bool addInterfaces = false, double wrappingLayerEpsilon = 0.01,
482-
bool boolMaterials = false) const {
471+
getSurfaceMesh(bool addInterfaces = false, bool sharpCorners = false,
472+
double wrappingLayerEpsilon = 0.01) const {
483473
auto mesh = viennals::Mesh<NumericType>::New();
484474
if (addInterfaces) {
485475
viennals::ToMultiSurfaceMesh<NumericType, D> meshConverter(
486476
mesh, 1e-12, wrappingLayerEpsilon);
487-
for (unsigned i = 0; i < levelSets_.size(); i++) {
488-
auto lsCopy = lsDomainType::New(levelSets_.at(i));
489-
if (i > 0 && boolMaterials) {
490-
viennals::BooleanOperation<NumericType, D>(
491-
lsCopy, levelSets_.at(i - 1),
492-
viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT)
493-
.apply();
494-
}
495-
meshConverter.insertNextLevelSet(lsCopy);
477+
for (const auto &ls : levelSets_) {
478+
meshConverter.insertNextLevelSet(ls);
496479
}
480+
meshConverter.setSharpCorners(sharpCorners);
497481
meshConverter.setMaterialMap(materialMap_->getMaterialMap());
498482
meshConverter.apply();
499483
} else {
@@ -510,46 +494,68 @@ VIENNAPS_TEMPLATE_ND(NumericType, D) class Domain {
510494
{"MaterialIds"})
511495
.apply();
512496

513-
viennals::ToSurfaceMesh<NumericType, D>(levelSets_.back(), mesh).apply();
497+
viennals::ToSurfaceMesh<NumericType, D> surfMesher(levelSets_.back(),
498+
mesh);
499+
surfMesher.setSharpCorners(sharpCorners);
500+
surfMesher.apply();
514501
}
515502

516503
return mesh;
517504
}
518505

506+
SmartPointer<viennals::Mesh<NumericType>>
507+
getHullMesh(NumericType bottomExtension = 0.0,
508+
bool sharpCorners = false) const {
509+
auto mesh = viennals::Mesh<NumericType>::New();
510+
viennals::ToHullMesh<NumericType, D> meshConverter(mesh);
511+
for (unsigned i = 0; i < levelSets_.size(); i++) {
512+
meshConverter.insertNextLevelSet(levelSets_.at(i));
513+
}
514+
meshConverter.setMaterialMap(materialMap_->getMaterialMap());
515+
meshConverter.setSharpCorners(sharpCorners);
516+
meshConverter.setBottomExtension(bottomExtension);
517+
meshConverter.apply();
518+
return mesh;
519+
}
520+
521+
// Save the level set as a VTK file.
522+
void saveLevelSetMesh(const std::string &fileName, int width = 1) {
523+
auto meshes = getLevelSetMesh(width);
524+
for (int i = 0; i < meshes.size(); i++) {
525+
viennals::VTKWriter<NumericType> writer(
526+
meshes[i], fileName + "_layer" + std::to_string(i) + ".vtp");
527+
writer.setMetaData(metaData_);
528+
writer.apply();
529+
}
530+
}
531+
519532
// Print the top Level-Set (surface) in a VTK file format (vtp).
520-
void saveSurfaceMesh(std::string fileName, bool addInterfaces = true,
521-
double wrappingLayerEpsilon = 0.01,
522-
bool boolMaterials = false) const {
533+
void saveSurfaceMesh(const std::string &fileName, bool addInterfaces = true,
534+
bool sharpCorners = false,
535+
double wrappingLayerEpsilon = 0.01) const {
523536
auto mesh =
524-
getSurfaceMesh(addInterfaces, wrappingLayerEpsilon, boolMaterials);
537+
getSurfaceMesh(addInterfaces, sharpCorners, wrappingLayerEpsilon);
525538
viennals::VTKWriter<NumericType> writer(mesh, fileName);
526539
writer.setMetaData(metaData_);
527540
writer.apply();
528541
}
529542

530-
// Save the domain as a volume mesh
531-
void
532-
saveVolumeMesh(std::string fileName,
533-
double wrappingLayerEpsilon = DEFAULT_WRAPPING_EPSILON) const {
534-
viennals::WriteVisualizationMesh<NumericType, D> writer;
535-
writer.setFileName(fileName);
536-
writer.setWrappingLayerEpsilon(wrappingLayerEpsilon);
537-
for (auto &ls : levelSets_) {
538-
writer.insertNextLevelSet(ls);
539-
}
540-
writer.setMaterialMap(materialMap_->getMaterialMap());
543+
void saveHullMesh(const std::string &fileName,
544+
NumericType bottomExtension = 0.0,
545+
bool sharpCorners = false) const {
546+
auto mesh = getHullMesh(bottomExtension, sharpCorners);
547+
viennals::VTKWriter<NumericType> writer(mesh, fileName);
541548
writer.setMetaData(metaData_);
542549
writer.apply();
543550
}
544551

552+
// Save the domain as a volume mesh
545553
void
546-
saveHullMesh(std::string fileName,
547-
double wrappingLayerEpsilon = DEFAULT_WRAPPING_EPSILON) const {
554+
saveVolumeMesh(const std::string &fileName,
555+
double wrappingLayerEpsilon = DEFAULT_WRAPPING_EPSILON) const {
548556
viennals::WriteVisualizationMesh<NumericType, D> writer;
549557
writer.setFileName(fileName);
550558
writer.setWrappingLayerEpsilon(wrappingLayerEpsilon);
551-
writer.setExtractHullMesh(true);
552-
writer.setExtractVolumeMesh(false);
553559
for (auto &ls : levelSets_) {
554560
writer.insertNextLevelSet(ls);
555561
}

python/pyWrapDimension.hpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -532,27 +532,31 @@ template <int D> void bindApi(py::module &module) {
532532
[](Domain<T, D> &self, bool hrle) { self.print(std::cout, hrle); },
533533
"Print the domain information.", py::arg("hrleInfo") = false)
534534
.def("show", &Domain<T, D>::show, "Render the domain using VTK.")
535+
// Mesh generation
535536
.def("getLevelSetMesh", &Domain<T, D>::getLevelSetMesh,
536537
py::arg("width") = 1,
537538
"Get the level set grids of layers in the domain.")
539+
.def("getSurfaceMesh", &Domain<T, D>::getSurfaceMesh,
540+
py::arg("addInterfaces") = false, py::arg("sharpCorners") = false,
541+
py::arg("wrappingLayerEpsilon") = 0.01,
542+
"Get the surface mesh of the domain")
543+
.def("getHullMesh", &Domain<T, D>::getHullMesh,
544+
py::arg("bottomExtension") = 0.0, py::arg("sharpCorners") = false)
545+
// Save to file
538546
.def("saveLevelSetMesh", &Domain<T, D>::saveLevelSetMesh,
539547
py::arg("filename"), py::arg("width") = 1,
540548
"Save the level set grids of layers in the domain.")
541-
.def("getSurfaceMesh", &Domain<T, D>::getSurfaceMesh,
542-
py::arg("addInterfaces") = false,
543-
py::arg("wrappingLayerEpsilon") = 1e-2,
544-
py::arg("boolMaterials") = false,
545-
"Get the surface mesh of the domain")
546549
.def("saveSurfaceMesh", &Domain<T, D>::saveSurfaceMesh,
547550
py::arg("filename"), py::arg("addInterfaces") = false,
551+
py::arg("sharpCorners") = false,
548552
py::arg("wrappingLayerEpsilon") = 1e-2,
549-
py::arg("boolMaterials") = false, "Save the surface of the domain.")
553+
"Save the surface of the domain.")
554+
.def("saveHullMesh", &Domain<T, D>::saveHullMesh, py::arg("filename"),
555+
py::arg("bottomExtension") = 0.0, py::arg("sharpCorners") = false,
556+
"Save the hull of the domain.")
550557
.def("saveVolumeMesh", &Domain<T, D>::saveVolumeMesh, py::arg("filename"),
551558
py::arg("wrappingLayerEpsilon") = 1e-2,
552559
"Save the volume representation of the domain.")
553-
.def("saveHullMesh", &Domain<T, D>::saveHullMesh, py::arg("filename"),
554-
py::arg("wrappingLayerEpsilon") = 1e-2,
555-
"Save the hull of the domain.")
556560
.def("saveLevelSets", &Domain<T, D>::saveLevelSets, py::arg("filename"))
557561
.def("clear", &Domain<T, D>::clear)
558562
.def("clearMetaData", &Domain<T, D>::clearMetaData,

python/viennaps/_core/__init__.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import collections.abc
66
import enum
77
import typing
88
import viennals._core
9-
import viennaps.d2
109
from viennaps import d2
11-
from viennaps import d3
10+
import viennaps.d2
1211
import viennaps.d3
12+
from viennaps import d3
1313
from . import constants
1414
from . import gpu
1515
from . import util

python/viennaps/d2/__init__.pyi

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ class Domain:
294294
"""
295295
Get the grid delta.
296296
"""
297+
def getHullMesh(self, bottomExtension: typing.SupportsFloat | typing.SupportsIndex = 0.0, sharpCorners: bool = False) -> viennals._core.Mesh:
298+
...
297299
def getLevelSetMesh(self, width: typing.SupportsInt | typing.SupportsIndex = 1) -> list[viennals._core.Mesh]:
298300
"""
299301
Get the level set grids of layers in the domain.
@@ -330,7 +332,7 @@ class Domain:
330332
"""
331333
Get the surface level set.
332334
"""
333-
def getSurfaceMesh(self, addInterfaces: bool = False, wrappingLayerEpsilon: typing.SupportsFloat | typing.SupportsIndex = 0.01, boolMaterials: bool = False) -> viennals._core.Mesh:
335+
def getSurfaceMesh(self, addInterfaces: bool = False, sharpCorners: bool = False, wrappingLayerEpsilon: typing.SupportsFloat | typing.SupportsIndex = 0.01) -> viennals._core.Mesh:
334336
"""
335337
Get the surface mesh of the domain
336338
"""
@@ -350,7 +352,7 @@ class Domain:
350352
...
351353
def removeTopLevelSet(self) -> None:
352354
...
353-
def saveHullMesh(self, filename: str, wrappingLayerEpsilon: typing.SupportsFloat | typing.SupportsIndex = 0.01) -> None:
355+
def saveHullMesh(self, filename: str, bottomExtension: typing.SupportsFloat | typing.SupportsIndex = 0.0, sharpCorners: bool = False) -> None:
354356
"""
355357
Save the hull of the domain.
356358
"""
@@ -360,7 +362,7 @@ class Domain:
360362
"""
361363
def saveLevelSets(self, filename: str) -> None:
362364
...
363-
def saveSurfaceMesh(self, filename: str, addInterfaces: bool = False, wrappingLayerEpsilon: typing.SupportsFloat | typing.SupportsIndex = 0.01, boolMaterials: bool = False) -> None:
365+
def saveSurfaceMesh(self, filename: str, addInterfaces: bool = False, sharpCorners: typing.SupportsFloat | typing.SupportsIndex = False, wrappingLayerEpsilon: bool = 0.01) -> None:
364366
"""
365367
Save the surface of the domain.
366368
"""

python/viennaps/d3/__init__.pyi

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ class Domain:
294294
"""
295295
Get the grid delta.
296296
"""
297+
def getHullMesh(self, bottomExtension: typing.SupportsFloat | typing.SupportsIndex = 0.0, sharpCorners: bool = False) -> viennals._core.Mesh:
298+
...
297299
def getLevelSetMesh(self, width: typing.SupportsInt | typing.SupportsIndex = 1) -> list[viennals._core.Mesh]:
298300
"""
299301
Get the level set grids of layers in the domain.
@@ -330,7 +332,7 @@ class Domain:
330332
"""
331333
Get the surface level set.
332334
"""
333-
def getSurfaceMesh(self, addInterfaces: bool = False, wrappingLayerEpsilon: typing.SupportsFloat | typing.SupportsIndex = 0.01, boolMaterials: bool = False) -> viennals._core.Mesh:
335+
def getSurfaceMesh(self, addInterfaces: bool = False, sharpCorners: bool = False, wrappingLayerEpsilon: typing.SupportsFloat | typing.SupportsIndex = 0.01) -> viennals._core.Mesh:
334336
"""
335337
Get the surface mesh of the domain
336338
"""
@@ -350,7 +352,7 @@ class Domain:
350352
...
351353
def removeTopLevelSet(self) -> None:
352354
...
353-
def saveHullMesh(self, filename: str, wrappingLayerEpsilon: typing.SupportsFloat | typing.SupportsIndex = 0.01) -> None:
355+
def saveHullMesh(self, filename: str, bottomExtension: typing.SupportsFloat | typing.SupportsIndex = 0.0, sharpCorners: bool = False) -> None:
354356
"""
355357
Save the hull of the domain.
356358
"""
@@ -360,7 +362,7 @@ class Domain:
360362
"""
361363
def saveLevelSets(self, filename: str) -> None:
362364
...
363-
def saveSurfaceMesh(self, filename: str, addInterfaces: bool = False, wrappingLayerEpsilon: typing.SupportsFloat | typing.SupportsIndex = 0.01, boolMaterials: bool = False) -> None:
365+
def saveSurfaceMesh(self, filename: str, addInterfaces: bool = False, sharpCorners: typing.SupportsFloat | typing.SupportsIndex = False, wrappingLayerEpsilon: bool = 0.01) -> None:
364366
"""
365367
Save the surface of the domain.
366368
"""

0 commit comments

Comments
 (0)