Compare commits

...

43 Commits

Author SHA1 Message Date
Christopher Lackner
a9e8f2a1c9 return invalid surfaceindex (index is 0 based) 2025-04-28 20:29:51 +02:00
Matthias Hochsteger
b84975586c Boundarylayer thickness limitation fix
Don't check for intersecting mapped trigs if only volume elements are
added (and no mapped surface elements).

In case of only inserted volume elements, we don't care about the limit
at special points.
2025-04-28 16:36:00 +02:00
Matthias Hochsteger
aa66cd11c4 Export Mesh.GetCurveOrder() to Python 2025-04-28 15:31:50 +02:00
Matthias Hochsteger
494b0ae37c code formatting in blayer files 2025-04-28 15:31:30 +02:00
Matthias Hochsteger
f42d0c0be4 Fix missing identifications in boundarylayer generation, some code refactoring 2025-04-28 15:30:29 +02:00
Matthias Hochsteger
b43eb033d2 Pass -DCMAKE_POLICY_VERSION_MINIMUM=3.5 to subprojects for cmake 4 compatibility 2025-04-23 08:39:58 +02:00
Matthias Hochsteger
1fc382867d Fix segfault in occ (use Handle when creating new Geom_Plane) 2025-04-15 18:39:20 +02:00
Schöberl, Joachim
6ea09e1151 Merge branch 'occ_wp_ellipse' into 'master'
add ellipse to occ workplane

See merge request ngsolve/netgen!705
2025-04-14 22:00:36 +02:00
Christopher Lackner
36cbd5fc00 add ellipse to occ workplane 2025-04-14 17:48:18 +02:00
Christopher Lackner
3a9060fc2f fix occ Ellipse function 2025-04-14 17:04:33 +02:00
Joachim Schoeberl
109e7ffcf7 fix for 1D meshing (without region names) 2025-04-14 10:40:41 +02:00
Christopher Lackner
1db8ea3500 also different BRepTools::Write on occ lower than 7.6 2025-04-14 09:12:08 +02:00
Christopher Lackner
b05c32675b check for binary output for older occ versions 2025-04-14 08:34:59 +02:00
Joachim Schoeberl
cb3eb0d355 common arrays of region names 2025-04-13 16:14:01 +02:00
Christopher Lackner
42294117bd 0 dim elements are not curved 2025-04-11 10:44:56 +02:00
Matthias Hochsteger
60c1151205 Utility function to draw lines (used for contact boundary in NGSolve) 2025-04-09 11:39:57 +02:00
Matthias Hochsteger
3f28651e63 Boundary layers - don't ignore edges on cylinder sides when smoothing growth vectors 2025-04-09 11:39:57 +02:00
Christopher Lackner
5a66cbee72 allow writing brep in different versions and binary 2025-04-04 08:54:32 +02:00
Christopher Lackner
788c782455 OCCGeometry properties to query subshapes in netgen-order 2025-03-31 09:16:44 +02:00
Matthias Hochsteger
12ef984e93 OCC - Set metricweight in 2d mesh optimization (like in CSG) 2025-03-26 16:29:32 +01:00
Matthias Hochsteger
f15ba64a90 LocalH::Find() utility function to find GradingBox
Simplifies code and avoids searching for same grading box twice in SetH().
2025-03-26 15:37:06 +01:00
Matthias Hochsteger
3b79dbc8ff Layer parameter for RestrictH 2025-03-26 15:19:11 +01:00
Christopher Lackner
7b13db740d fix bisect with periodic boundaries 2025-03-25 11:00:24 +01:00
Christopher Lackner
78994da199 1d occ meshes 2025-03-19 17:38:51 +01:00
Hochsteger, Matthias
42c1818784 Merge branch 'fix_colors_occ' into 'master'
fix colors from step read if they are set on solid for subshapes

See merge request ngsolve/netgen!704
2025-03-19 09:49:34 +01:00
Christopher Lackner
97f869207e fix colors from step read if they are set on solid for subshapes 2025-03-19 08:58:49 +01:00
Schöberl, Joachim
951e20a7e4 Merge branch 'from_pyocc' into 'master'
add From_PyOCC function to convert swig pyocc shape to netgen.occ

See merge request ngsolve/netgen!703
2025-03-17 15:21:44 +01:00
Christopher Lackner
8cde49627b remove debug cout 2025-03-17 11:23:40 +01:00
Christopher Lackner
36c9201ffc add From_PyOCC function to convert swig pyocc shape to netgen.occ 2025-03-17 11:20:19 +01:00
Christopher Lackner
8478ff5078 add edges to occ visualization data 2025-03-16 09:31:06 +01:00
Christopher Lackner
714158e928 fix and improve occ visualizationdata function 2025-03-15 04:34:16 +01:00
Christopher Lackner
9399f753c4 allow list of profiles in PipeShell 2025-03-14 11:36:00 +01:00
Lackner, Christopher
8944322e60 Merge branch 'cleanup_searchtree_elementindex' into 'master'
move all searchtrees to use elementindex

See merge request ngsolve/netgen!702
2025-03-13 19:55:29 +01:00
Christopher Lackner
15bd6cbed0 take autoscale value on drawn regions only 2025-03-13 18:49:28 +01:00
Christopher Lackner
b8d722d6a8 remove debug output 2025-03-13 18:41:38 +01:00
Christopher Lackner
7aae5369c4 move all searchtrees to use elementindex 2025-03-13 18:39:21 +01:00
Christopher Lackner
787c6043fa set timestamp in element search tree 2025-03-13 10:10:04 +01:00
Christopher Lackner
d240203932 fix 1d FindPointInElement 2025-03-07 18:01:00 +01:00
Schöberl, Joachim
0c789fb04f Merge branch 'findpointinelement' into 'master'
Improvements to FindPointInElement interface code

See merge request ngsolve/netgen!701
2025-03-07 17:42:24 +01:00
Christopher Lackner
9204b079f6 Improvements to FindPointInElement interface code 2025-03-07 17:14:31 +01:00
Hochsteger, Matthias
2778b934e6 Merge branch 'fix_conform_segments' into 'master'
Fixes to conform to free segments

See merge request ngsolve/netgen!700
2025-03-06 19:11:34 +01:00
Matthias Hochsteger
627e89d579 Fixes to conform to free segments 2025-03-06 18:53:16 +01:00
Christopher Lackner
bc194027a2 fix edges and new domains in BoundaryLayer2d with make_new_domain=True 2025-03-04 09:59:56 +01:00
33 changed files with 833 additions and 641 deletions

View File

@ -57,7 +57,7 @@ set_vars(SUBPROJECT_CMAKE_ARGS CMAKE_C_COMPILER)
set_vars(SUBPROJECT_CMAKE_ARGS CMAKE_CXX_COMPILER)
set_vars(SUBPROJECT_CMAKE_ARGS CMAKE_BUILD_TYPE)
set(SUBPROJECT_CMAKE_ARGS "${SUBPROJECT_CMAKE_ARGS};-DCMAKE_POSITION_INDEPENDENT_CODE=ON" CACHE INTERNAL "")
set(SUBPROJECT_CMAKE_ARGS "${SUBPROJECT_CMAKE_ARGS};-DCMAKE_POSITION_INDEPENDENT_CODE=ON;-DCMAKE_POLICY_VERSION_MINIMUM=3.5" CACHE INTERNAL "")
if(USE_CCACHE)
find_program(CCACHE_FOUND NAMES ccache ccache.bat)

View File

@ -109,6 +109,7 @@ if(APPLE)
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}/Contents/MacOS
-DTCL_INCLUDE_PATH=${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tcl.framework/Headers
-DTK_INCLUDE_PATH=${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tk.framework/Headers
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
${SUBPROJECT_ARGS}
)

View File

@ -718,7 +718,7 @@ namespace netgen
mesh -> LoadLocalMeshSize (mparam.meshsizefilename);
for (auto mspnt : mparam.meshsize_points)
mesh -> RestrictLocalH (mspnt.pnt, mspnt.h);
mesh -> RestrictLocalH (mspnt.pnt, mspnt.h, mspnt.layer);
}
spoints.SetSize(0);

View File

@ -72,13 +72,17 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<0> (size_t nr) const
ret.facets.base = POINTINDEX_BASE;
ret.facets.ptr = (int*)&el.pnum;
/*
if (mesh->GetDimension() == 1)
ret.mat = *(mesh->GetBCNamePtr(el.index-1));
else if (mesh->GetDimension() == 2)
ret.mat = *(mesh->GetCD2NamePtr(el.index-1));
else
ret.mat = *(mesh->GetCD3NamePtr(el.index-1));
*/
ret.mat = mesh->GetRegionName(0, el.index);
ret.is_curved = false;
return ret;
}
@ -96,6 +100,8 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<1> (size_t nr) const
ret.index = el.edgenr;
else
ret.index = el.si;
/*
if (mesh->GetDimension() == 2)
ret.mat = *(mesh->GetBCNamePtr(el.si-1));
else
@ -105,6 +111,8 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<1> (size_t nr) const
else
ret.mat = *(mesh->GetMaterialPtr(el.si));
}
*/
ret.mat = mesh->GetRegionName(1, ret.index);
ret.points.num = el.GetNP();
ret.points.ptr = (int*)&(el[0]);

View File

@ -651,14 +651,14 @@ int Ng_FindElementOfPoint (double * p, double * lami, int build_searchtree,
{
Point3d p3d(p[0], p[1], p[2]);
ind =
mesh->GetElementOfPoint(p3d, lami, dummy, build_searchtree != 0);
mesh->GetElementOfPoint(p3d, lami, dummy, build_searchtree != 0) + 1;
}
else
{
double lam3[3];
Point3d p2d(p[0], p[1], 0);
ind =
mesh->GetElementOfPoint(p2d, lam3, dummy, build_searchtree != 0);
mesh->GetSurfaceElementOfPoint(p2d, lam3, dummy, build_searchtree != 0) + 1;
if (ind > 0)
{
@ -697,7 +697,7 @@ int Ng_FindSurfaceElementOfPoint (double * p, double * lami, int build_searchtre
{
Point3d p3d(p[0], p[1], p[2]);
ind =
mesh->GetSurfaceElementOfPoint(p3d, lami, dummy, build_searchtree != 0);
mesh->GetSurfaceElementOfPoint(p3d, lami, dummy, build_searchtree != 0) + 1;
}
else
{

View File

@ -1011,68 +1011,28 @@ namespace netgen
int * const indices, int numind) const
{
switch (mesh->GetDimension())
Point<3> p(hp[0], 0., 0.);
if(mesh->GetDimension() > 1)
p[1] = hp[1];
if(mesh->GetDimension() == 3)
p[2] = hp[2];
for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)
{
case 1:
{
Point<3> p(hp[0], 0,0);
for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)
{
auto & seg = (*mesh)[si];
Point<3> p1 = (*mesh)[seg[0]];
Point<3> p2 = (*mesh)[seg[1]];
double lam = (p(0)-p1(0)) / (p2(0)-p1(0));
if (lam >= -1e-10 && lam <= 1+1e-10)
{
lami[0] = 1-lam;
return si;
}
}
}
break;
case 2:
{
Point<3> p(hp[0], hp[1],0);
try
{
auto ind = mesh->GetSurfaceElementOfPoint(p, lami, nullptr,
build_searchtree);
return ind - 1;
}
catch(const NgException & e) // quads not implemented curved yet
{
for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)
{
auto & seg = (*mesh)[si];
Point<3> p1 = (*mesh)[seg[0]];
Point<3> p2 = (*mesh)[seg[1]];
double lam;
double r;
if (fabs(p2[0]-p1[0]) >= fabs(p2[1]-p1[1]))
{
lam = (p[0]-p1[0])/(p2[0]-p1[0]);
r = p[1] - p1[1] - lam*(p2[1]-p1[1]);
}
else
{
lam = (p[1]-p1[1])/(p2[1]-p1[1]);
r = p[0] - p1[0] - lam*(p2[0]-p1[0]);
}
if ( lam >= -1e-10 && lam <= 1+1e-10 && fabs(r) <= 1e-10 )
{
lami[0] = 1-lam;
return si;
}
}
}
}
break;
case 3:
default:
throw Exception("FindElementOfPoint<1> only implemented for mesh-dimension 1 and 2!");
break;
auto & seg = (*mesh)[si];
Point<3> p1 = (*mesh)[seg[0]];
Point<3> p2 = (*mesh)[seg[1]];
Vec<3> v1 = p2-p1;
Vec<3> v2 = p-p1;
double lam = v1*v2 / v1.Length2();
double lam2 = (v2 - lam * v1).Length() / v1.Length();
if (lam >= -1e-10 && lam <= 1+1e-10 && lam2 < 1e-10)
{
lami[0] = 1-lam;
return si;
}
}
return -1;
}
@ -1083,37 +1043,26 @@ namespace netgen
int * const indices, int numind) const
{
NgArray<int> dummy(numind);
for (int i = 0; i < numind; i++) dummy[i] = indices[i]+1;
Point<3> pp(p[0], p[1], 0.);
if(mesh->GetDimension() == 3)
pp[2] = p[2];
FlatArray<int> ind(numind, indices);
double lam3[3];
int ind;
if (mesh->GetDimension() == 2)
auto elnr = mesh->GetSurfaceElementOfPoint(pp, lam3, ind, build_searchtree);
if(elnr.IsValid())
{
Point<3> p2d(p[0], p[1], 0);
ind = mesh->GetElementOfPoint(p2d, lam3, &dummy, build_searchtree);
}
else
{
Point3d p3d(p[0], p[1], p[2]);
ind = mesh->GetSurfaceElementOfPoint(p3d, lam3, &dummy, build_searchtree);
}
if (ind > 0)
{
if(mesh->SurfaceElement(ind).GetType()==QUAD || mesh->SurfaceElement(ind).GetType()==TRIG6)
if((*mesh)[elnr].GetType() == QUAD || (*mesh)[elnr].GetType() == TRIG6)
{
lami[0] = lam3[0];
lami[1] = lam3[1];
}
else
else
{
lami[0] = 1-lam3[0]-lam3[1];
lami[1] = lam3[0];
}
}
return ind-1;
return elnr;
}
@ -1124,13 +1073,9 @@ namespace netgen
int * const indices, int numind) const
{
NgArray<int> dummy(numind);
for (int i = 0; i < numind; i++) dummy[i] = indices[i]+1;
Point<3> p3d(p[0], p[1], p[2]);
int ind =
mesh->GetElementOfPoint(p3d, lami, &dummy, build_searchtree);
return ind-1;
Point<3> pp(p[0], p[1], p[2]);
FlatArray<int> ind(numind, indices);
return mesh->GetElementOfPoint(pp, lami, ind, build_searchtree);
}
void Ngx_Mesh :: Curve (int order)

View File

@ -607,7 +607,7 @@ namespace netgen
const_cast<Mesh&> (mesh).Compress();
const_cast<Mesh&> (mesh).CalcSurfacesOfNode();
const_cast<Mesh&> (mesh).RebuildSurfaceElementLists();
const_cast<Mesh&> (mesh).BuildElementSearchTree();
const_cast<Mesh&> (mesh).BuildElementSearchTree(3);
int np = mesh.GetNP();

View File

@ -66,7 +66,7 @@ void WriteFluentFormat (const Mesh & mesh,
int i2, j2;
NgArray<INDEX_3> surfaceelp;
NgArray<int> surfaceeli;
NgArray<int> locels;
Array<ElementIndex> locels;
//no cells=no tets
//no faces=2*tets
@ -79,7 +79,7 @@ void WriteFluentFormat (const Mesh & mesh,
snprintf (str, size(str), "(13 (4 1 %x 2 3)(",noverbface); //hexadecimal!!!
outfile << str << endl;
const_cast<Mesh&> (mesh).BuildElementSearchTree();
const_cast<Mesh&> (mesh).BuildElementSearchTree(3);
for (i = 1; i <= ne; i++)
{
@ -117,12 +117,9 @@ void WriteFluentFormat (const Mesh & mesh,
int eli2 = 0;
int stopsig = 0;
for (i2 = 1; i2 <= nel; i2++)
for (auto locind : locels)
{
locind = locels.Get(i2);
//cout << " locind=" << locind << endl;
Element el2 = mesh.VolumeElement(locind);
Element el2 = mesh[locind];
//if (inverttets)
// el2.Invert();
@ -130,7 +127,7 @@ void WriteFluentFormat (const Mesh & mesh,
{
el2.GetFace(j2, face2);
if (face2.HasFace(face)) {eli2 = locind; stopsig = 1; break;}
if (face2.HasFace(face)) {eli2 = locind+1; stopsig = 1; break;}
}
if (stopsig) break;
}

View File

@ -474,7 +474,7 @@ namespace netgen
}
for(const auto& mspnt : mparam.meshsize_points)
mesh.RestrictLocalH(mspnt.pnt, mspnt.h);
mesh.RestrictLocalH(mspnt.pnt, mspnt.h, mspnt.layer);
mesh.LoadLocalMeshSize(mparam.meshsizefilename);
}
@ -1220,6 +1220,7 @@ namespace netgen
{
PrintMessage(3, "Optimization step ", i);
meshopt.SetFaceIndex(k+1);
meshopt.SetMetricWeight (mparam.elsizeweight);
int innerstep = 0;
for(auto optstep : mparam.optimize2d)
{
@ -1314,6 +1315,13 @@ namespace netgen
if(multithread.terminate || mparam.perfstepsend <= MESHCONST_MESHEDGES)
return 0;
if(dimension == 1)
{
FinalizeMesh(*mesh);
mesh->SetDimension(1);
return 0;
}
if (mparam.perfstepsstart <= MESHCONST_MESHSURFACE)
{
MeshSurface(*mesh, mparam);

View File

@ -4061,6 +4061,8 @@ namespace netgen
{
PointIndices<2> oi2(identmap[i2[0]],
identmap[i2[1]]);
if((!oi2[0].IsValid()) || (!oi2[1].IsValid()))
continue;
oi2.Sort();
if (cutedges.Used (oi2))
{

View File

@ -14,7 +14,7 @@ namespace netgen
struct SpecialPointException : public Exception
{
SpecialPointException()
SpecialPointException ()
: Exception("") {}
};
@ -101,14 +101,14 @@ Vec<3> CalcGrowthVector (FlatArray<Vec<3>> ns)
return gw;
}
SpecialBoundaryPoint ::GrowthGroup ::GrowthGroup(FlatArray<int> faces_,
FlatArray<Vec<3>> normals)
SpecialBoundaryPoint ::GrowthGroup ::GrowthGroup (FlatArray<int> faces_,
FlatArray<Vec<3>> normals)
{
faces = faces_;
growth_vector = CalcGrowthVector(normals);
}
SpecialBoundaryPoint ::SpecialBoundaryPoint(
SpecialBoundaryPoint ::SpecialBoundaryPoint (
const std::map<int, Vec<3>>& normals)
{
// find opposing face normals
@ -146,7 +146,7 @@ SpecialBoundaryPoint ::SpecialBoundaryPoint(
growth_groups.Append(GrowthGroup(g2_faces, normals2));
}
Vec<3> BoundaryLayerTool ::getEdgeTangent(PointIndex pi, int edgenr, FlatArray<Segment*> segs)
Vec<3> BoundaryLayerTool ::getEdgeTangent (PointIndex pi, int edgenr, FlatArray<Segment*> segs)
{
Vec<3> tangent = 0.0;
ArrayMem<PointIndex, 2> pts;
@ -171,7 +171,7 @@ Vec<3> BoundaryLayerTool ::getEdgeTangent(PointIndex pi, int edgenr, FlatArray<S
return tangent.Normalize();
}
void BoundaryLayerTool ::LimitGrowthVectorLengths()
void BoundaryLayerTool ::LimitGrowthVectorLengths ()
{
static Timer tall("BoundaryLayerTool::LimitGrowthVectorLengths");
RegionTimer rtall(tall);
@ -220,7 +220,7 @@ bool HaveSingleSegments (const Mesh& mesh)
// duplicates segments (and sets seg.si accordingly) to have a unified data
// structure for all geometry types
void BuildSegments (Mesh& mesh, bool have_single_segments, Array<Segment> & segments, Array<Segment> & free_segments)
void BuildSegments (Mesh& mesh, bool have_single_segments, Array<Segment>& segments, Array<Segment>& free_segments)
{
// auto& topo = mesh.GetTopology();
@ -234,11 +234,11 @@ void BuildSegments (Mesh& mesh, bool have_single_segments, Array<Segment> & segm
free_segments.Append(seg);
continue;
}
if(!have_single_segments)
{
segments.Append(seg);
continue;
}
if (!have_single_segments)
{
segments.Append(seg);
continue;
}
mesh.GetTopology().GetSegmentSurfaceElements(segi + 1, surf_els);
for (auto seli : surf_els)
{
@ -284,8 +284,8 @@ void MergeAndAddSegments (Mesh& mesh, FlatArray<Segment> segments, FlatArray<Seg
addSegment(seg);
}
BoundaryLayerTool::BoundaryLayerTool(Mesh& mesh_,
const BoundaryLayerParameters& params_)
BoundaryLayerTool::BoundaryLayerTool (Mesh& mesh_,
const BoundaryLayerParameters& params_)
: mesh(mesh_), topo(mesh_.GetTopology()), params(params_)
{
static Timer timer("BoundaryLayerTool::ctor");
@ -318,7 +318,7 @@ BoundaryLayerTool::BoundaryLayerTool(Mesh& mesh_,
si_map[i] = i;
}
void BoundaryLayerTool ::CreateNewFaceDescriptors()
void BoundaryLayerTool ::CreateNewFaceDescriptors ()
{
surfacefacs.SetSize(nfd_old + 1);
surfacefacs = 0.0;
@ -360,7 +360,7 @@ void BoundaryLayerTool ::CreateNewFaceDescriptors()
throw Exception("Surface " + to_string(si) + " is not a boundary of the domain to be grown into!");
}
void BoundaryLayerTool ::CreateFaceDescriptorsSides()
void BoundaryLayerTool ::CreateFaceDescriptorsSides ()
{
if (insert_only_volume_elements)
return;
@ -400,7 +400,7 @@ void BoundaryLayerTool ::CreateFaceDescriptorsSides()
}
}
void BoundaryLayerTool ::CalculateGrowthVectors()
void BoundaryLayerTool ::CalculateGrowthVectors ()
{
growthvectors.SetSize(np);
growthvectors = 0.;
@ -457,7 +457,7 @@ void BoundaryLayerTool ::CalculateGrowthVectors()
}
Array<Array<pair<SegmentIndex, int>>, SegmentIndex>
BoundaryLayerTool ::BuildSegMap()
BoundaryLayerTool ::BuildSegMap ()
{
// Bit array to keep track of segments already processed
BitArray segs_done(nseg + 1);
@ -536,7 +536,7 @@ BoundaryLayerTool ::BuildSegMap()
return segmap;
}
BitArray BoundaryLayerTool ::ProjectGrowthVectorsOnSurface()
BitArray BoundaryLayerTool ::ProjectGrowthVectorsOnSurface ()
{
BitArray in_surface_direction(nfd_old + 1);
in_surface_direction.Clear();
@ -596,7 +596,7 @@ BitArray BoundaryLayerTool ::ProjectGrowthVectorsOnSurface()
return in_surface_direction;
}
void BoundaryLayerTool ::InsertNewElements(
void BoundaryLayerTool ::InsertNewElements (
FlatArray<Array<pair<SegmentIndex, int>>, SegmentIndex> segmap,
const BitArray& in_surface_direction)
{
@ -879,61 +879,61 @@ void BoundaryLayerTool ::InsertNewElements(
auto p2el = mesh.CreatePoint2ElementTable();
for (SurfaceElementIndex si = 0; si < nse; si++)
{
// copy because surfaceels array will be resized!
const auto sel = mesh[si];
if (moved_surfaces.Test(sel.GetIndex()))
const auto iface = sel.GetIndex();
if (moved_surfaces.Test(iface))
{
Array<PointIndex> points(sel.PNums());
if (surfacefacs[sel.GetIndex()] > 0)
const auto np = sel.GetNP();
ArrayMem<PointIndex, 4> points(sel.PNums());
if (surfacefacs[iface] > 0)
Swap(points[0], points[2]);
ArrayMem<int, 4> groups(points.Size());
for (auto i : Range(points))
groups[i] = getClosestGroup(sel[i], si);
groups[i] = getClosestGroup(points[i], si);
bool add_volume_element = true;
for (auto pi : sel.PNums())
for (auto pi : points)
if (numGroups(pi) > 1)
add_volume_element = false;
Element el(2 * np);
el.PNums().Range(np, 2 * np) = points;
auto new_index = new_mat_nrs[iface];
if (new_index == -1)
throw Exception("Boundary " + ToString(iface) + " with name " + mesh.GetBCName(iface - 1) + " extruded, but no new material specified for it!");
el.SetIndex(new_index);
for (auto j : Range(par_heights))
{
auto eltype = points.Size() == 3 ? PRISM : HEX;
Element el(eltype);
for (auto i : Range(points))
el[i] = points[i];
for (auto i : Range(points))
points[i] = newPoint(sel.PNums()[i], j, groups[i]);
if (surfacefacs[sel.GetIndex()] > 0)
Swap(points[0], points[2]);
for (auto i : Range(points))
el[sel.PNums().Size() + i] = points[i];
auto new_index = new_mat_nrs[sel.GetIndex()];
if (new_index == -1)
throw Exception("Boundary " + ToString(sel.GetIndex()) + " with name " + mesh.GetBCName(sel.GetIndex() - 1) + " extruded, but no new material specified for it!");
el.SetIndex(new_mat_nrs[sel.GetIndex()]);
el.PNums().Range(0, np) = el.PNums().Range(np, 2 * np);
for (auto i : Range(np))
el[np + i] = newPoint(points[i], j, groups[i]);
if (add_volume_element)
mesh.AddVolumeElement(el);
else
{
// Let the volume mesher fill the hole with pyramids/tets
// To insert pyramids, we need close surface identifications on open
// quads
for (auto i : Range(points))
if (numGroups(sel[i]) == 1)
// To insert pyramids, we need close surface identifications on open quads
for (auto i : Range(np))
if (numGroups(el[i]) == 1)
{
auto pi0 = el[i];
auto pi1 = el[i + points.Size()];
auto pi1 = el[np + i];
auto nr = identifications.Get(pi0, pi1);
if (nr == 0)
identifications.Add(el[i], el[i + points.Size()], identnr);
identifications.Add(pi0, pi1, identnr);
}
}
}
Element2d newel = sel;
for (auto i : Range(points))
newel[i] = newPoint(sel[i], -1, groups[i]);
newel.SetIndex(si_map[sel.GetIndex()]);
for (auto i : Range(np))
newel[i] = newPoint(points[i], -1, groups[i]);
if (surfacefacs[iface] > 0)
Swap(newel[0], newel[2]); // swap back
newel.SetIndex(si_map[iface]);
new_sels.Append(newel);
}
if (is_boundary_moved.Test(sel.GetIndex()))
if (is_boundary_moved.Test(iface))
{
auto& sel = mesh[si];
for (auto& p : sel.PNums())
@ -1065,7 +1065,7 @@ void BoundaryLayerTool ::InsertNewElements(
}
}
void BoundaryLayerTool ::SetDomInOut()
void BoundaryLayerTool ::SetDomInOut ()
{
if (insert_only_volume_elements)
return;
@ -1081,7 +1081,7 @@ void BoundaryLayerTool ::SetDomInOut()
}
}
void BoundaryLayerTool ::SetDomInOutSides()
void BoundaryLayerTool ::SetDomInOutSides ()
{
// Set the domin/domout entries for face descriptors on the "side" of new boundary layers
if (insert_only_volume_elements)
@ -1155,7 +1155,7 @@ void BoundaryLayerTool ::SetDomInOutSides()
}
}
void BoundaryLayerTool ::AddSegments()
void BoundaryLayerTool ::AddSegments ()
{
auto& new_segs =
insert_only_volume_elements ? new_segments_on_moved_bnd : new_segments;
@ -1199,14 +1199,14 @@ void BoundaryLayerTool ::AddSegments()
mesh.AddSegment(seg);
}
void BoundaryLayerTool ::AddSurfaceElements()
void BoundaryLayerTool ::AddSurfaceElements ()
{
for (auto& sel :
insert_only_volume_elements ? new_sels_on_moved_bnd : new_sels)
mesh.AddSurfaceElement(sel);
}
void BoundaryLayerTool ::ProcessParameters()
void BoundaryLayerTool ::ProcessParameters ()
{
if (int* bc = get_if<int>(&params.boundary); bc)
{
@ -1374,7 +1374,7 @@ void BoundaryLayerTool ::ProcessParameters()
domains.Invert();
}
void BoundaryLayerTool ::Perform()
void BoundaryLayerTool ::Perform ()
{
if (domains.NumSet() == 0)
return;

View File

@ -22,15 +22,15 @@ struct SpecialBoundaryPoint
Vec<3> growth_vector;
Array<PointIndex> new_points;
GrowthGroup(FlatArray<int> faces_, FlatArray<Vec<3>> normals);
GrowthGroup(const GrowthGroup&) = default;
GrowthGroup() = default;
GrowthGroup (FlatArray<int> faces_, FlatArray<Vec<3>> normals);
GrowthGroup (const GrowthGroup&) = default;
GrowthGroup () = default;
};
Array<GrowthGroup> growth_groups;
Vec<3> separating_direction;
SpecialBoundaryPoint(const std::map<int, Vec<3>>& normals);
SpecialBoundaryPoint() = default;
SpecialBoundaryPoint (const std::map<int, Vec<3>>& normals);
SpecialBoundaryPoint () = default;
};
DLL_HEADER void GenerateBoundaryLayer (Mesh& mesh,
@ -41,7 +41,7 @@ DLL_HEADER int /* new_domain_number */ GenerateBoundaryLayer2 (Mesh& mesh, int d
class BoundaryLayerTool
{
public:
BoundaryLayerTool(Mesh& mesh_, const BoundaryLayerParameters& params_);
BoundaryLayerTool (Mesh& mesh_, const BoundaryLayerParameters& params_);
void ProcessParameters ();
void Perform ();

View File

@ -243,10 +243,6 @@ namespace netgen
Array<SegmentIndex> segments;
// surface index map
Array<int> si_map(mesh.GetNFD()+2);
si_map = -1;
// int fd_old = mesh.GetNFD();
int max_edge_nr = -1;
@ -254,8 +250,8 @@ namespace netgen
for(const auto& seg : line_segments)
{
if(seg.epgeominfo[0].edgenr > max_edge_nr)
max_edge_nr = seg.epgeominfo[0].edgenr;
if(seg.edgenr > max_edge_nr)
max_edge_nr = seg.edgenr;
if(seg.domin > max_domain)
max_domain = seg.domin;
if(seg.domout > max_domain)
@ -263,6 +259,7 @@ namespace netgen
}
int new_domain = max_domain+1;
int new_edge_nr = max_edge_nr+1;
BitArray active_boundaries(max_edge_nr+1);
BitArray active_segments(nseg);
@ -288,7 +285,10 @@ namespace netgen
// int new_fd_index =
mesh.AddFaceDescriptor(new_fd);
if(should_make_new_domain)
mesh.SetBCName(new_domain-1, "mapped_" + mesh.GetBCName(domain-1));
{
mesh.SetMaterial(new_domain, "layer_" + mesh.GetMaterial(domain));
mesh.SetBCName(new_edge_nr - 1, "moved");
}
}
for(auto segi : Range(line_segments))
@ -618,8 +618,6 @@ namespace netgen
}
}
map<pair<PointIndex, PointIndex>, int> seg2edge;
// insert new elements ( and move old ones )
for(auto si : moved_segs)
{
@ -629,8 +627,6 @@ namespace netgen
auto & pm0 = mapto[seg[0]];
auto & pm1 = mapto[seg[1]];
// auto newindex = si_map[domain];
Segment s = seg;
s.geominfo[0] = {};
s.geominfo[1] = {};
@ -638,10 +634,10 @@ namespace netgen
s[1] = pm1.Last();
s[2] = PointIndex::INVALID;
auto pair = s[0] < s[1] ? make_pair(s[0], s[1]) : make_pair(s[1], s[0]);
if(seg2edge.find(pair) == seg2edge.end())
seg2edge[pair] = ++max_edge_nr;
s.edgenr = seg2edge[pair];
s.si = seg.si;
s.edgenr = new_edge_nr;
s.epgeominfo[0].edgenr = -1;
s.epgeominfo[1].edgenr = -1;
s.si = s.edgenr;
mesh.AddSegment(s);
for ( auto i : Range(thicknesses))

View File

@ -70,7 +70,7 @@ BuildNeighbors (FlatArray<PointIndex> points, const Mesh& mesh)
return neighbors;
}
void BoundaryLayerTool ::InterpolateGrowthVectors()
void BoundaryLayerTool ::InterpolateGrowthVectors ()
{
point_types.SetSize(mesh.GetNP());
for (auto p : mesh.Points().Range())
@ -139,7 +139,7 @@ void BoundaryLayerTool ::InterpolateGrowthVectors()
faces.Append(sei);
}
if (faces.Size() == 2)
if (faces.Size() == 2 && mesh[faces[0]].GetIndex() != mesh[faces[1]].GetIndex())
{
auto n0 = getNormal(mesh[faces[0]]);
auto n1 = getNormal(mesh[faces[1]]);
@ -299,7 +299,7 @@ void BoundaryLayerTool ::InterpolateGrowthVectors()
}
}
void BoundaryLayerTool ::InterpolateSurfaceGrowthVectors()
void BoundaryLayerTool ::InterpolateSurfaceGrowthVectors ()
{
static Timer tall("InterpolateSurfaceGrowthVectors");
RegionTimer rtall(tall);
@ -399,7 +399,7 @@ void BoundaryLayerTool ::InterpolateSurfaceGrowthVectors()
growthvectors[pi] += corrections[pi];
}
void BoundaryLayerTool ::FixSurfaceElements()
void BoundaryLayerTool ::FixSurfaceElements ()
{
static Timer tall("FixSurfaceElements");
RegionTimer rtall(tall);

View File

@ -29,7 +29,7 @@ struct GrowthVectorLimiter
Array<PointIndex, PointIndex> map_from;
Table<SurfaceElementIndex, PointIndex> p2sel;
GrowthVectorLimiter(BoundaryLayerTool& tool_)
GrowthVectorLimiter (BoundaryLayerTool& tool_)
: tool(tool_), params(tool_.params), mesh(tool_.mesh), height(tool_.total_height), growthvectors(tool_.growthvectors), map_from(mesh.Points().Size())
{
changed_domains = tool.domains;
@ -287,7 +287,7 @@ struct GrowthVectorLimiter
if (factor == 0.0)
return;
// for (PointIndex pi : IntRange(tool.np, mesh.GetNP()))
for (PointIndex pi : mesh.Points().Range().Modify(tool.np,0))
for (PointIndex pi : mesh.Points().Range().Modify(tool.np, 0))
{
// auto pi_from = map_from[pi];
std::set<PointIndex> pis;
@ -464,8 +464,7 @@ struct GrowthVectorLimiter
}
template <typename TFunc>
void FindTreeIntersections (double trig_shift, double seg_shift, TFunc f,
TBitArray<PointIndex> * relevant_points = nullptr)
void FindTreeIntersections (double trig_shift, double seg_shift, TFunc f, TBitArray<PointIndex>* relevant_points = nullptr)
{
static Timer t("GrowthVectorLimiter::FindTreeIntersections");
RegionTimer rt(t);
@ -506,6 +505,25 @@ struct GrowthVectorLimiter
RegionTimer reg(t);
// check if surface trigs are intersecting each other
bool changed = true;
std::set<PointIndex> special_points;
if (tool.insert_only_volume_elements)
for (auto [pi, special_point] : tool.special_boundary_points)
{
special_points.insert(pi);
for (auto& group : special_point.growth_groups)
special_points.insert(group.new_points.Last());
}
auto skip_trig = [&] (const Element2d& tri) {
if (!tool.insert_only_volume_elements)
return false;
for (auto pi : tri.PNums())
if (special_points.find(pi) != special_points.end())
return true;
return false;
};
while (changed)
{
changed = false;
@ -517,6 +535,9 @@ struct GrowthVectorLimiter
{
const Element2d& tri = Get(sei);
if (skip_trig(tri))
continue;
Box<3> box(Box<3>::EMPTY_BOX);
for (PointIndex pi : tri.PNums())
box.Add(GetPoint(pi, 1.0, true));
@ -529,6 +550,9 @@ struct GrowthVectorLimiter
{
const Element2d& tri = Get(sei);
if (skip_trig(tri))
continue;
Box<3> box(Box<3>::EMPTY_BOX);
for (PointIndex pi : tri.PNums())
box.Add(GetPoint(pi, 1.0, true));
@ -629,7 +653,7 @@ struct GrowthVectorLimiter
size_t limit_counter = 1;
TBitArray<PointIndex> relevant_points, relevant_points_next;
relevant_points.SetSize(mesh.Points().Size() + 1);
relevant_points.SetSize(mesh.Points().Size() + 1);
relevant_points_next.SetSize(mesh.Points().Size() + 1);
relevant_points.Set();
@ -685,8 +709,9 @@ struct GrowthVectorLimiter
for (auto pi : Range(growthvectors))
check_point(pi);
for (auto& [special_pi, special_point] : tool.special_boundary_points)
check_point(special_pi);
if (!tool.insert_only_volume_elements)
for (auto& [special_pi, special_point] : tool.special_boundary_points)
check_point(special_pi);
}
void Perform ()

View File

@ -9,6 +9,25 @@
namespace netgen
{
inline int GetVolElement(const Mesh& mesh, const Point<3>& p,
double* lami)
{
if(mesh.GetDimension() == 3)
{
auto ei = mesh.GetElementOfPoint(p, lami, true);
if(!ei.IsValid())
return -1;
return ei;
}
else
{
auto ei = mesh.GetSurfaceElementOfPoint(p, lami, true);
if(!ei.IsValid())
return -1;
return ei;
}
}
RKStepper :: ~RKStepper()
{
delete a;
@ -190,9 +209,9 @@ namespace netgen
for(int i=0; i<potential_startpoints.Size(); i++)
{
int elnr = mesh.GetElementOfPoint(potential_startpoints[i],lami,true) - 1;
if(elnr == -1)
continue;
int elnr = GetVolElement(mesh, potential_startpoints[i], lami);
if (elnr == -1)
continue;
mesh.SetPointSearchStartElement(elnr);
@ -289,8 +308,7 @@ namespace netgen
dirstart.SetSize(0);
dirstart.Append(0);
int startelnr = mesh.GetElementOfPoint(startpoint,startlami,true) - 1;
int startelnr = GetVolElement(mesh, startpoint,startlami);
(*testout) << "p = " << startpoint << "; elnr = " << startelnr << endl;
if (startelnr == -1)
return;
@ -342,7 +360,7 @@ namespace netgen
Point<3> newp;
while(!stepper.GetNextData(newp,dummyt,h) && elnr != -1)
{
elnr = mesh.GetElementOfPoint(newp,lami,true) - 1;
elnr = GetVolElement(mesh, newp, lami);
if(elnr != -1)
{
mesh.SetPointSearchStartElement(elnr);

View File

@ -2194,7 +2194,7 @@ void MeshOptimize3d :: SwapImproveSurface (
double MeshOptimize3d :: SwapImprove2 ( ElementIndex eli1, int face,
Table<ElementIndex, PointIndex> & elementsonnode,
DynamicTable<SurfaceElementIndex, PointIndex> & belementsonnode, bool check_only )
DynamicTable<SurfaceElementIndex, PointIndex> & belementsonnode, bool conform_segments, bool check_only )
{
PointIndex pi1, pi2, pi3, pi4, pi5;
Element el21(TET), el22(TET), el31(TET), el32(TET), el33(TET);
@ -2228,28 +2228,31 @@ double MeshOptimize3d :: SwapImprove2 ( ElementIndex eli1, int face,
}
bool bface = 0;
for (int k = 0; k < belementsonnode[pi1].Size(); k++)
{
const Element2d & bel =
mesh[belementsonnode[pi1][k]];
if(!conform_segments)
{
bool bface = 0;
for (int k = 0; k < belementsonnode[pi1].Size(); k++)
{
const Element2d & bel =
mesh[belementsonnode[pi1][k]];
bool bface1 = 1;
for (int l = 0; l < 3; l++)
if (bel[l] != pi1 && bel[l] != pi2 && bel[l] != pi3)
bool bface1 = 1;
for (int l = 0; l < 3; l++)
if (bel[l] != pi1 && bel[l] != pi2 && bel[l] != pi3)
{
bface1 = 0;
break;
}
if (bface1)
{
bface1 = 0;
bface = 1;
break;
}
if (bface1)
{
bface = 1;
break;
}
}
if (bface) return 0.0;
if (bface) return 0.0;
}
FlatArray<ElementIndex> row = elementsonnode[pi1];
@ -2367,11 +2370,11 @@ double MeshOptimize3d :: SwapImprove2 ( ElementIndex eli1, int face,
2 -> 3 conversion
*/
void MeshOptimize3d :: SwapImprove2 ()
void MeshOptimize3d :: SwapImprove2 (bool conform_segments)
{
static Timer t("MeshOptimize3d::SwapImprove2"); RegionTimer reg(t);
if (goal == OPT_CONFORM) return;
if (!conform_segments && goal == OPT_CONFORM) return;
mesh.BuildBoundaryEdges(false);
@ -2433,7 +2436,7 @@ void MeshOptimize3d :: SwapImprove2 ()
for (int j = 0; j < 4; j++)
{
double d_badness = SwapImprove2( eli1, j, elementsonnode, belementsonnode, true);
double d_badness = SwapImprove2( eli1, j, elementsonnode, belementsonnode, conform_segments, true);
if(d_badness<0.0)
my_faces_with_improvement.Append( std::make_tuple(d_badness, eli1, j) );
}
@ -2449,7 +2452,7 @@ void MeshOptimize3d :: SwapImprove2 ()
{
if(mesh[eli].IsDeleted())
continue;
if(SwapImprove2( eli, j, elementsonnode, belementsonnode, false) < 0.0)
if(SwapImprove2( eli, j, elementsonnode, belementsonnode, conform_segments, false) < 0.0)
cnt++;
}

View File

@ -45,8 +45,8 @@ public:
void SwapImprove (const TBitArray<ElementIndex> * working_elements = NULL);
void SwapImproveSurface (const TBitArray<ElementIndex> * working_elements = NULL,
const NgArray< idmap_type* > * idmaps = NULL);
void SwapImprove2 ();
double SwapImprove2 (ElementIndex eli1, int face, Table<ElementIndex, PointIndex> & elementsonnode, DynamicTable<SurfaceElementIndex, PointIndex> & belementsonnode, bool check_only=false );
void SwapImprove2 (bool conform_segments = false);
double SwapImprove2 (ElementIndex eli1, int face, Table<ElementIndex, PointIndex> & elementsonnode, DynamicTable<SurfaceElementIndex, PointIndex> & belementsonnode, bool conform_segments, bool check_only=false );
void ImproveMesh() { mesh.ImproveMesh(mp, goal); }

View File

@ -196,54 +196,41 @@ namespace netgen
fabs (p(1) - root->xmid[1]) > root->h2)
return;
if (GetH(p) <= 1.2 * h) return;
GradingBox * box = root;
GradingBox * nbox = root;
GradingBox * ngb;
int childnr;
double x1[3], x2[3];
while (nbox)
{
box = nbox;
childnr = 0;
if (p(0) > box->xmid[0]) childnr += 1;
if (p(1) > box->xmid[1]) childnr += 2;
nbox = box->childs[childnr];
};
GradingBox * box = Find(p);
if (box->HOpt() <= 1.2 * h) return;
while (2 * box->h2 > h)
{
childnr = 0;
if (p(0) > box->xmid[0]) childnr += 1;
if (p(1) > box->xmid[1]) childnr += 2;
int childnr = 0;
double x1[3], x2[3];
double h2 = box->h2;
if (childnr & 1)
if (p(0) > box->xmid[0])
{
childnr += 1;
x1[0] = box->xmid[0];
x2[0] = x1[0]+h2; // box->x2[0];
x2[0] = x1[0]+h2;
}
else
{
x2[0] = box->xmid[0];
x1[0] = x2[0]-h2; // box->x1[0];
x1[0] = x2[0]-h2;
}
if (childnr & 2)
if (p(1) > box->xmid[1])
{
childnr += 2;
x1[1] = box->xmid[1];
x2[1] = x1[1]+h2; // box->x2[1];
x2[1] = x1[1]+h2;
}
else
{
x2[1] = box->xmid[1];
x1[1] = x2[1]-h2; // box->x1[1];
x1[1] = x2[1]-h2;
}
x1[2] = x2[2] = 0;
ngb = new GradingBox (x1, x2);
auto ngb = new GradingBox (x1, x2);
box->childs[childnr] = ngb;
ngb->father = box;
@ -276,67 +263,52 @@ namespace netgen
fabs (p(2) - root->xmid[2]) > root->h2)
return;
if (GetH(p) <= 1.2 * h) return;
GradingBox * box = root;
GradingBox * nbox = root;
GradingBox * ngb;
int childnr;
double x1[3], x2[3];
while (nbox)
{
box = nbox;
childnr = 0;
if (p(0) > box->xmid[0]) childnr += 1;
if (p(1) > box->xmid[1]) childnr += 2;
if (p(2) > box->xmid[2]) childnr += 4;
nbox = box->childs[childnr];
};
GradingBox * box = Find(p);
if (box->HOpt() <= 1.2 * h) return;
while (2 * box->h2 > h)
{
childnr = 0;
if (p(0) > box->xmid[0]) childnr += 1;
if (p(1) > box->xmid[1]) childnr += 2;
if (p(2) > box->xmid[2]) childnr += 4;
double x1[3], x2[3];
int childnr = 0;
double h2 = box->h2;
if (childnr & 1)
if (p(0) > box->xmid[0])
{
childnr += 1;
x1[0] = box->xmid[0];
x2[0] = x1[0]+h2; // box->x2[0];
x2[0] = x1[0]+h2;
}
else
{
x2[0] = box->xmid[0];
x1[0] = x2[0]-h2; // box->x1[0];
x1[0] = x2[0]-h2;
}
if (childnr & 2)
if (p(1) > box->xmid[1])
{
childnr += 2;
x1[1] = box->xmid[1];
x2[1] = x1[1]+h2; // box->x2[1];
x2[1] = x1[1]+h2;
}
else
{
x2[1] = box->xmid[1];
x1[1] = x2[1]-h2; // box->x1[1];
x1[1] = x2[1]-h2;
}
if (childnr & 4)
if (p(2) > box->xmid[2])
{
childnr += 4;
x1[2] = box->xmid[2];
x2[2] = x1[2]+h2; // box->x2[2];
x2[2] = x1[2]+h2;
}
else
{
x2[2] = box->xmid[2];
x1[2] = x2[2]-h2; // box->x1[2];
x1[2] = x2[2]-h2;
}
ngb = new GradingBox (x1, x2);
auto ngb = new GradingBox (x1, x2);
box->childs[childnr] = ngb;
ngb->father = box;
@ -366,37 +338,7 @@ namespace netgen
double LocalH :: GetH (Point<3> x) const
{
const GradingBox * box = root;
if (dimension == 2)
{
while (1)
{
int childnr = 0;
if (x(0) > box->xmid[0]) childnr += 1;
if (x(1) > box->xmid[1]) childnr += 2;
if (box->childs[childnr])
box = box->childs[childnr];
else
return box->hopt;
}
}
else
{
while (1)
{
int childnr = 0;
if (x(0) > box->xmid[0]) childnr += 1;
if (x(1) > box->xmid[1]) childnr += 2;
if (x(2) > box->xmid[2]) childnr += 4;
if (box->childs[childnr])
box = box->childs[childnr];
else
return box->hopt;
}
}
return Find(x)->HOpt();
}
@ -488,6 +430,41 @@ namespace netgen
}
GradingBox * LocalH :: Find (Point<3> p) const
{
GradingBox * box = root;
if (dimension == 2)
{
while (1)
{
int childnr = 0;
if (p(0) > box->xmid[0]) childnr += 1;
if (p(1) > box->xmid[1]) childnr += 2;
if (box->childs[childnr])
box = box->childs[childnr];
else
return box;
}
}
else
{
while (1)
{
int childnr = 0;
if (p(0) > box->xmid[0]) childnr += 1;
if (p(1) > box->xmid[1]) childnr += 2;
if (p(2) > box->xmid[2]) childnr += 4;
if (box->childs[childnr])
box = box->childs[childnr];
else
return box;
}
}
return nullptr;
}
void LocalH :: FindInnerBoxes (const AdFront3 & adfront,
int (*testinner)(const Point3d & p1))

View File

@ -54,6 +54,7 @@ namespace netgen
Point<3> PMid() const { return Point<3> (xmid[0], xmid[1], xmid[2]); }
double H2() const { return h2; }
double HOpt() const { return hopt; }
bool HasChilds() const
{
@ -119,6 +120,8 @@ namespace netgen
void CutBoundary (const Box<3> & box)
{ CutBoundaryRec (box.PMin(), box.PMax(), root); }
GradingBox * Find(Point<3> p) const;
/// find inner boxes
void FindInnerBoxes (const class AdFront3 & adfront,

View File

@ -12,15 +12,15 @@
namespace netgen
{
int Find3dElement (const Mesh& mesh,
const netgen::Point<3> & p,
double * lami,
const NgArray<int> * const indices,
BoxTree<3> * searchtree,
const bool allowindex = true)
ElementIndex Find3dElement (const Mesh& mesh,
const netgen::Point<3> & p,
double * lami,
optional<FlatArray<int>> indices,
BoxTree<3, ElementIndex> * searchtree,
const bool allowindex)
{
int ne = 0;
NgArray<int> locels;
Array<ElementIndex> locels;
if (searchtree)
{
searchtree->GetIntersecting (p, p, locels);
@ -29,92 +29,90 @@ namespace netgen
else
ne = mesh.GetNE();
for (int i = 1; i <= ne; i++)
for (auto i : Range(ne))
{
int ii;
ElementIndex ei;
if (searchtree)
ii = locels.Get(i);
ei = locels[i];
else
ii = i;
ei = i;
if(indices != NULL && indices->Size() > 0)
if(indices && indices->Size() > 0)
{
bool contained = indices->Contains(mesh.VolumeElement(ii).GetIndex());
bool contained = indices->Contains(mesh[ei].GetIndex());
if((allowindex && !contained) || (!allowindex && contained)) continue;
}
if(mesh.PointContainedIn3DElement(p,lami,ii))
return ii;
if(mesh.PointContainedIn3DElement(p,lami,ei))
return ei;
}
// Not found, try uncurved variant:
for (int i = 1; i <= ne; i++)
for (auto i : Range(ne))
{
int ii;
ElementIndex ei;
if (searchtree)
ii = locels.Get(i);
ei = locels[i];
else
ii = i;
ei = i;
if(indices != NULL && indices->Size() > 0)
if(indices && indices->Size() > 0)
{
bool contained = indices->Contains(mesh.VolumeElement(ii).GetIndex());
bool contained = indices->Contains(mesh[ei].GetIndex());
if((allowindex && !contained) || (!allowindex && contained)) continue;
}
if(mesh.PointContainedIn3DElementOld(p,lami,ii))
if(mesh.PointContainedIn3DElementOld(p,lami,ei))
{
(*testout) << "WARNING: found element of point " << p <<" only for uncurved mesh" << endl;
return ii;
return ei;
}
}
return 0;
return ElementIndex::INVALID;
}
int Find2dElement (const Mesh& mesh,
const netgen::Point<3> & p,
double * lami,
const NgArray<int> * const indices,
BoxTree<3> * searchtree,
const bool allowindex = true)
SurfaceElementIndex
Find2dElement (const Mesh& mesh,
const netgen::Point<3> & p,
double * lami,
std::optional<FlatArray<int>> indices,
BoxTree<3, SurfaceElementIndex> * searchtree,
bool allowindex)
{
double vlam[3];
int velement = 0;
ElementIndex velement = ElementIndex::INVALID;
if(mesh.GetNE())
velement = Find3dElement(mesh, p,vlam,NULL,searchtree,allowindex);
{
if(searchtree)
const_cast<Mesh&>(mesh).BuildElementSearchTree(3);
velement = Find3dElement(mesh, p,vlam, nullopt,searchtree ? mesh.GetElementSearchTree() : nullptr,allowindex);
}
//(*testout) << "p " << p << endl;
//(*testout) << "velement " << velement << endl;
// first try to find a volume element containing p and project to face
if(velement!=0)
if(velement.IsValid())
{
auto & topology = mesh.GetTopology();
// NgArray<int> faces;
// topology.GetElementFaces(velement,faces);
auto faces = Array<int> (topology.GetFaces(ElementIndex(velement-1)));
//(*testout) << "faces " << faces << endl;
for(int i=0; i<faces.Size(); i++)
faces[i] = topology.GetFace2SurfaceElement(faces[i])+1;
//(*testout) << "surfel " << faces << endl;
const auto & fnrs = topology.GetFaces(velement);
auto faces = ArrayMem<SurfaceElementIndex,4>();
for(auto face : fnrs)
faces.Append(topology.GetFace2SurfaceElement(face));
for(int i=0; i<faces.Size(); i++)
{
if(faces[i] == 0)
if(!faces[i].IsValid())
continue;
auto sel = mesh.SurfaceElement(faces[i]);
if(indices && indices->Size() != 0 && !indices->Contains(sel.GetIndex()))
if(indices && indices->Size() > 0 && !indices->Contains(sel.GetIndex()))
continue;
auto & el = mesh.VolumeElement(velement);
auto & el = mesh[velement];
if (el.GetType() == TET)
{
double lam4[4] = { vlam[0], vlam[1], vlam[2], 1.0-vlam[0]-vlam[1]-vlam[2] };
@ -127,7 +125,7 @@ namespace netgen
for(auto k : Range(4))
if(sel[j] == el[k])
lami[j-1] = lam4[k]/(1.0-face_lam);
return faces[i];
return SurfaceElementIndex(faces[i]);
}
}
@ -139,9 +137,8 @@ namespace netgen
// Did't find any matching face of a volume element, search 2d elements directly
int ne;
NgArray<int> locels;
// TODO: build search tree for surface elements
if (!mesh.GetNE() && searchtree)
Array<SurfaceElementIndex> locels;
if (searchtree)
{
searchtree->GetIntersecting (p, p, locels);
ne = locels.Size();
@ -149,37 +146,38 @@ namespace netgen
else
ne = mesh.GetNSE();
for (int i = 1; i <= ne; i++)
for (auto i : Range(ne))
{
int ii;
SurfaceElementIndex ii;
if (locels.Size())
ii = locels.Get(i);
ii = locels[i];
else
ii = i;
if(indices != NULL && indices->Size() > 0)
if(indices && indices->Size() > 0)
{
bool contained = indices->Contains(mesh.SurfaceElement(ii).GetIndex());
bool contained = indices->Contains(mesh[ii].GetIndex());
if((allowindex && !contained) || (!allowindex && contained)) continue;
}
if(mesh.PointContainedIn2DElement(p,lami,ii)) return ii;
if(mesh.PointContainedIn2DElement(p,lami,ii))
return ii;
}
return 0;
return SurfaceElementIndex::INVALID;
}
int Find1dElement (const Mesh& mesh,
const netgen::Point<3> & p,
double * lami,
const NgArray<int> * const indices,
BoxTree<3> * searchtree,
const bool allowindex = true)
SegmentIndex Find1dElement (const Mesh& mesh,
const netgen::Point<3> & p,
double * lami,
std::optional<FlatArray<int>> indices,
BoxTree<3> * searchtree,
const bool allowindex = true)
{
double vlam[3];
int velement = Find2dElement(mesh, p, vlam, NULL, searchtree, allowindex);
if(velement == 0)
if(searchtree)
const_cast<Mesh&>(mesh).BuildElementSearchTree(2);
auto velement = Find2dElement(mesh, p, vlam, nullopt, searchtree ? mesh.GetSurfaceElementSearchTree() : nullptr, allowindex);
if(!velement.IsValid())
return 0;
vlam[2] = 1.-vlam[0] - vlam[1];
@ -235,8 +233,8 @@ namespace netgen
: topology(*this), surfarea(*this)
{
lochfunc = {nullptr};
elementsearchtree = nullptr;
elementsearchtreets = NextTimeStamp();
for(auto i : Range(4))
elementsearchtreets[i] = NextTimeStamp();
majortimestamp = timestamp = NextTimeStamp();
hglob = 1e10;
hmin = 0;
@ -4821,6 +4819,21 @@ namespace netgen
for (auto & seg : LineSegments())
seg.si = seg.edgenr;
}
if (dimension == 3 && dim == 1)
{
for(auto str : materials)
delete str;
materials.SetSize(0);
for(auto str : bcnames)
delete str;
bcnames.SetSize(0);
for(auto str: cd2names)
materials.Append(str);
cd2names.SetSize(0);
for(auto str : cd3names)
bcnames.Append(str);
cd3names.SetSize(0);
}
dimension = dim;
}
@ -5251,122 +5264,95 @@ namespace netgen
RebuildSurfaceElementLists();
}
void Mesh :: BuildElementSearchTree ()
void Mesh :: BuildElementSearchTree (int dim)
{
if (elementsearchtreets == GetTimeStamp()) return;
if(dim < 2)
return;
if (elementsearchtreets[dim] == GetTimeStamp())
return;
{
std::lock_guard<std::mutex> guard(buildsearchtree_mutex);
if (elementsearchtreets != GetTimeStamp())
// check again to see if some other thread built while waiting for lock
if (elementsearchtreets[dim] == GetTimeStamp()) return;
elementsearchtreets[dim] = GetTimeStamp();
PrintMessage (4, "Rebuild element searchtree dim " + ToString(dim));
Point3d pmin, pmax;
GetBox(pmin, pmax);
Box<3> box(pmin, pmax);
if (dim == 3)
elementsearchtree_vol = make_unique<BoxTree<3, ElementIndex>>(box);
else
elementsearchtree_surf = make_unique<BoxTree<3, SurfaceElementIndex>>(box);
if (dim == 3)
{
NgLock lock(mutex);
lock.Lock();
PrintMessage (4, "Rebuild element searchtree");
elementsearchtree = nullptr;
int ne = (dimension == 2) ? GetNSE() : GetNE();
if (dimension == 3 && !GetNE() && GetNSE())
ne = GetNSE();
if (ne)
for(auto ei : volelements.Range())
{
if (dimension == 2 || (dimension == 3 && !GetNE()) )
const auto& el = volelements[ei];
Box<3> box (Box<3>::EMPTY_BOX);
for (auto pi : el.PNums())
box.Add (points[pi]);
if(el.IsCurved() && curvedelems->IsElementCurved(ei))
{
Box<3> box (Box<3>::EMPTY_BOX);
for (SurfaceElementIndex sei = 0; sei < ne; sei++)
// box.Add (points[surfelements[sei].PNums()]);
for (auto pi : surfelements[sei].PNums())
box.Add (points[pi]);
box.Increase (1.01 * box.Diam());
elementsearchtree = make_unique<BoxTree<3>> (box);
for (SurfaceElementIndex sei = 0; sei < ne; sei++)
{
// box.Set (points[surfelements[sei].PNums()]);
// add edge/face midpoints to box
auto eltype = el.GetType();
const auto verts = topology.GetVertices(eltype);
Box<3> box (Box<3>::EMPTY_BOX);
for (auto pi : surfelements[sei].PNums())
box.Add (points[pi]);
const auto edges = FlatArray<const ELEMENT_EDGE>(topology.GetNEdges(eltype), topology.GetEdges0(eltype));
for (const auto & edge: edges) {
netgen::Point<3> lam = netgen::Point<3>(0.5* (verts[edge[0]] + verts[edge[1]]));
auto p = netgen::Point<3>(0.0);
curvedelems->CalcElementTransformation(lam,ei,p);
box.Add(p);
}
auto & el = surfelements[sei];
if(el.IsCurved() && curvedelems->IsSurfaceElementCurved(sei))
{
netgen::Point<2> lami [4] = {netgen::Point<2>(0.5,0), netgen::Point<2>(0,0.5), netgen::Point<2>(0.5,0.5), netgen::Point<2>(1./3,1./3)};
for (auto lam : lami)
{
netgen::Point<3> x;
Mat<3,2> Jac;
curvedelems->CalcSurfaceTransformation(lam,sei,x,Jac);
box.Add (x);
}
box.Scale(1.2);
}
elementsearchtree -> Insert (box, sei+1);
const auto faces = FlatArray<const ELEMENT_FACE>(topology.GetNFaces(eltype), topology.GetFaces0(eltype));
for (const auto & face: faces) {
netgen::Vec<3> lam = netgen::Vec<3>(verts[face[0]] + verts[face[1]] + verts[face[2]]);
if(face[3] != -1) {
lam += netgen::Vec<3>(verts[face[3]]);
lam *= 0.25;
}
else
lam *= 1.0/3;
auto p = netgen::Point<3>(0.0);
curvedelems->CalcElementTransformation(netgen::Point<3>(lam),ei,p);
box.Add(p);
}
}
else
box.Scale(1.2);
elementsearchtree_vol -> Insert (box, ei);
}
}
else if (dim == 2)
{
for (auto ei : Range(surfelements))
{
const auto& el = surfelements[ei];
Box<3> box (Box<3>::EMPTY_BOX);
for (auto pi : el.PNums())
box.Add (points[pi]);
if(el.IsCurved() && curvedelems->IsSurfaceElementCurved(ei))
{
Box<3> box (Box<3>::EMPTY_BOX);
for (ElementIndex ei = 0; ei < ne; ei++)
// box.Add (points[volelements[ei].PNums()]);
for (auto pi : volelements[ei].PNums())
box.Add (points[pi]);
box.Increase (1.01 * box.Diam());
elementsearchtree = make_unique<BoxTree<3>> (box);
for (ElementIndex ei = 0; ei < ne; ei++)
netgen::Point<2> lami [4] = {netgen::Point<2>(0.5,0), netgen::Point<2>(0,0.5), netgen::Point<2>(0.5,0.5), netgen::Point<2>(1./3,1./3)};
for (auto lam : lami)
{
// box.Set (points[volelements[ei].PNums()]);
netgen::Point<3> x;
Mat<3,2> Jac;
Box<3> box (Box<3>::EMPTY_BOX);
for (auto pi : volelements[ei].PNums())
box.Add (points[pi]);
auto & el = volelements[ei];
if(el.IsCurved() && curvedelems->IsElementCurved(ei))
{
// add edge/face midpoints to box
auto eltype = el.GetType();
const auto verts = topology.GetVertices(eltype);
const auto edges = FlatArray<const ELEMENT_EDGE>(topology.GetNEdges(eltype), topology.GetEdges0(eltype));
for (const auto & edge: edges) {
netgen::Point<3> lam = netgen::Point<3>(0.5* (verts[edge[0]] + verts[edge[1]]));
auto p = netgen::Point<3>(0.0);
curvedelems->CalcElementTransformation(lam,ei,p);
box.Add(p);
}
const auto faces = FlatArray<const ELEMENT_FACE>(topology.GetNFaces(eltype), topology.GetFaces0(eltype));
for (const auto & face: faces) {
netgen::Vec<3> lam = netgen::Vec<3>(verts[face[0]] + verts[face[1]] + verts[face[2]]);
if(face[3] != -1) {
lam += netgen::Vec<3>(verts[face[3]]);
lam *= 0.25;
}
else
lam *= 1.0/3;
auto p = netgen::Point<3>(0.0);
curvedelems->CalcElementTransformation(netgen::Point<3>(lam),ei,p);
box.Add(p);
}
box.Scale(1.2);
}
elementsearchtree -> Insert (box, ei+1);
curvedelems->CalcSurfaceTransformation(lam,ei,x,Jac);
box.Add (x);
}
box.Scale(1.2);
}
elementsearchtreets = GetTimeStamp();
elementsearchtree_surf -> Insert (box, ei);
}
}
}
@ -5406,7 +5392,7 @@ namespace netgen
bool Mesh :: PointContainedIn2DElement(const Point3d & p,
double lami[3],
const int element,
SurfaceElementIndex ei,
bool consider3D) const
{
Vec3d col1, col2, col3;
@ -5417,9 +5403,9 @@ namespace netgen
//SZ
if(SurfaceElement(element).GetType()==QUAD)
if(surfelements[ei].GetType()==QUAD)
{
const Element2d & el = SurfaceElement(element);
const Element2d & el = surfelements[ei];
const Point3d & p1 = Point(el.PNum(1));
const Point3d & p2 = Point(el.PNum(2));
@ -5438,7 +5424,7 @@ namespace netgen
int i = 0;
while(delta > 1e-16 && i < maxits)
{
curvedelems->CalcSurfaceTransformation(lam,element-1,x,Jac);
curvedelems->CalcSurfaceTransformation(lam,ei,x,Jac);
rhs = p - x;
Jac.Solve(rhs,deltalam);
lam += deltalam;
@ -5767,7 +5753,7 @@ namespace netgen
{
// SurfaceElement(element).GetTets (loctets);
loctrigs.SetSize(1);
loctrigs.Elem(1) = SurfaceElement(element);
loctrigs.Elem(1) = surfelements[ei];
@ -5802,11 +5788,11 @@ namespace netgen
//(*testout) << "col1 " << col1 << " col2 " << col2 << " col3 " << col3 << " rhs " << rhs << endl;
//(*testout) << "sol " << sol << endl;
if (SurfaceElement(element).GetType() ==TRIG6 || curvedelems->IsSurfaceElementCurved(element-1))
if (surfelements[ei].GetType() ==TRIG6 || curvedelems->IsSurfaceElementCurved(ei))
{
// netgen::Point<2> lam(1./3,1./3);
netgen::Point<2> lam(sol.X(), sol.Y());
if(SurfaceElement(element).GetType() != TRIG6)
if(surfelements[ei].GetType() != TRIG6)
{
lam[0] = 1-sol.X()-sol.Y();
lam[1] = sol.X();
@ -5825,7 +5811,7 @@ namespace netgen
const int maxits = 30;
while(delta > 1e-16 && i<maxits)
{
curvedelems->CalcSurfaceTransformation(lam,element-1,x,Jac);
curvedelems->CalcSurfaceTransformation(lam,ei,x,Jac);
rhs = p-x;
Jac.Solve(rhs,deltalam);
@ -5844,7 +5830,7 @@ namespace netgen
sol.X() = lam(0);
sol.Y() = lam(1);
if (SurfaceElement(element).GetType() !=TRIG6 )
if (surfelements[ei].GetType() !=TRIG6 )
{
sol.Z() = sol.X();
sol.X() = sol.Y();
@ -5876,7 +5862,7 @@ namespace netgen
bool Mesh :: PointContainedIn3DElement(const Point3d & p,
double lami[3],
const int element) const
ElementIndex ei) const
{
//bool oldresult = PointContainedIn3DElementOld(p,lami,element);
//(*testout) << "old result: " << oldresult
@ -5887,7 +5873,7 @@ namespace netgen
const double eps = 1.e-4;
const Element & el = VolumeElement(element);
const Element & el = volelements[ei];
netgen::Point<3> lam = 0.0;
@ -5922,7 +5908,7 @@ namespace netgen
const int maxits = 30;
while(delta > 1e-16 && i<maxits)
{
curvedelems->CalcElementTransformation(lam,element-1,x,Jac);
curvedelems->CalcElementTransformation(lam,ei,x,Jac);
rhs = p-x;
Jac.Solve(rhs,deltalam);
@ -6044,86 +6030,72 @@ namespace netgen
}
int Mesh :: GetElementOfPoint (const netgen::Point<3> & p,
double lami[3],
bool build_searchtree,
const int index,
const bool allowindex) const
ElementIndex Mesh :: GetElementOfPoint (const netgen::Point<3> & p,
double* lami,
bool build_searchtree,
int index,
bool allowindex) const
{
if(index != -1)
{
NgArray<int> dummy(1);
Array<int> dummy(1);
dummy[0] = index;
return GetElementOfPoint(p,lami,&dummy,build_searchtree,allowindex);
return GetElementOfPoint(p,lami,dummy,build_searchtree,allowindex);
}
else
return GetElementOfPoint(p,lami,NULL,build_searchtree,allowindex);
return GetElementOfPoint(p,lami,nullopt,build_searchtree,allowindex);
}
int Mesh :: GetElementOfPoint (const netgen::Point<3> & p,
double lami[3],
const NgArray<int> * const indices,
bool build_searchtree,
const bool allowindex) const
ElementIndex Mesh :: GetElementOfPoint (const netgen::Point<3> & p,
double* lami,
std::optional<FlatArray<int>> indices,
bool build_searchtree,
bool allowindex) const
{
if ( (dimension == 2 && !GetNSE()) ||
(dimension == 3 && !GetNE() && !GetNSE()) )
return -1;
if (build_searchtree)
const_cast<Mesh&>(*this).BuildElementSearchTree ();
if (dimension == 2 || (dimension==3 && !GetNE() && GetNSE()))
return Find2dElement(*this, p, lami, indices, elementsearchtree.get(), allowindex);
return Find3dElement(*this, p, lami, indices, elementsearchtree.get(), allowindex);
const_cast<Mesh&>(*this).BuildElementSearchTree (3);
return Find3dElement(*this, p, lami, indices, elementsearchtree_vol.get(), allowindex);
}
int Mesh :: GetSurfaceElementOfPoint (const netgen::Point<3> & p,
double lami[3],
bool build_searchtree,
const int index,
const bool allowindex) const
SurfaceElementIndex Mesh ::
GetSurfaceElementOfPoint (const netgen::Point<3> & p,
double* lami,
bool build_searchtree,
int index,
bool allowindex) const
{
if(index != -1)
if(index != -1)
{
NgArray<int> dummy(1);
Array<int> dummy(1);
dummy[0] = index;
return GetSurfaceElementOfPoint(p,lami,&dummy,build_searchtree,allowindex);
return GetSurfaceElementOfPoint(p,lami,dummy,build_searchtree,allowindex);
}
else
return GetSurfaceElementOfPoint(p,lami,NULL,build_searchtree,allowindex);
return GetSurfaceElementOfPoint(p,lami,nullopt,build_searchtree,allowindex);
}
int Mesh :: GetSurfaceElementOfPoint (const netgen::Point<3> & p,
double lami[3],
const NgArray<int> * const indices,
bool build_searchtree,
const bool allowindex) const
SurfaceElementIndex Mesh ::
GetSurfaceElementOfPoint (const netgen::Point<3> & p,
double* lami,
std::optional<FlatArray<int>> indices,
bool build_searchtree,
bool allowindex) const
{
if (!GetNE() && build_searchtree)
const_cast<Mesh&>(*this).BuildElementSearchTree ();
if (dimension == 2)
return Find1dElement(*this, p, lami, indices, elementsearchtree.get(), allowindex);
else
return Find2dElement(*this, p, lami, indices, elementsearchtree.get(), allowindex);
return 0;
if (build_searchtree)
const_cast<Mesh&>(*this).BuildElementSearchTree(2);
return Find2dElement(*this, p, lami, indices, elementsearchtree_surf.get(), allowindex);
}
void Mesh::GetIntersectingVolEls(const Point3d& p1, const Point3d& p2,
NgArray<int> & locels) const
Array<ElementIndex> & locels) const
{
elementsearchtree->GetIntersecting (p1, p2, locels);
elementsearchtree_vol->GetIntersecting (p1, p2, locels);
}
void Mesh :: SplitIntoParts()
@ -7441,9 +7413,10 @@ namespace netgen
}
string Mesh :: defaultmat = "default";
string_view Mesh :: defaultmat_sv = "default";
const string & Mesh :: GetMaterial (int domnr) const
{
if (domnr <= materials.Size())
if (domnr <= materials.Size() && materials[domnr-1])
return *materials[domnr-1];
static string emptystring("default");
return emptystring;

View File

@ -128,6 +128,13 @@ namespace netgen
*/
NgArray<EdgeDescriptor> edgedecoding;
Array<string*> region_name_cd[4];
Array<string*> & materials = region_name_cd[0];
Array<string*> & bcnames = region_name_cd[1];
Array<string*> & cd2names = region_name_cd[2];
Array<string*> & cd3names = region_name_cd[3];
/*
/// sub-domain materials
Array<string*> materials;
@ -139,7 +146,8 @@ namespace netgen
/// labels for co dim 3 bbboundary conditions
Array<string*> cd3names;
*/
/// Periodic surface, close surface, etc. identifications
unique_ptr<Identifications> ident;
@ -148,9 +156,10 @@ namespace netgen
int numvertices;
/// geometric search tree for interval intersection search
unique_ptr<BoxTree<3>> elementsearchtree;
unique_ptr<BoxTree<3, ElementIndex>> elementsearchtree_vol;
unique_ptr<BoxTree<3, SurfaceElementIndex>> elementsearchtree_surf;
/// time stamp for tree
mutable int elementsearchtreets;
mutable size_t elementsearchtreets[4];
/// element -> face, element -> edge etc ...
MeshTopology topology;
@ -200,11 +209,11 @@ namespace netgen
DLL_HEADER bool PointContainedIn2DElement(const Point3d & p,
double lami[3],
const int element,
SurfaceElementIndex element,
bool consider3D = false) const;
DLL_HEADER bool PointContainedIn3DElement(const Point3d & p,
double lami[3],
const int element) const;
ElementIndex element) const;
DLL_HEADER bool PointContainedIn3DElementOld(const Point3d & p,
double lami[3],
const int element) const;
@ -663,35 +672,48 @@ namespace netgen
/// build box-search tree
DLL_HEADER void BuildElementSearchTree ();
DLL_HEADER void BuildElementSearchTree (int dim);
BoxTree<3, ElementIndex>* GetElementSearchTree () const
{
return elementsearchtree_vol.get();
}
BoxTree<3, SurfaceElementIndex>* GetSurfaceElementSearchTree () const
{
return elementsearchtree_surf.get();
}
void SetPointSearchStartElement(const int el) const {ps_startelement = el;}
/// gives element of point, barycentric coordinates
DLL_HEADER int GetElementOfPoint (const netgen::Point<3> & p,
double * lami,
bool build_searchtree = 0,
const int index = -1,
const bool allowindex = true) const;
DLL_HEADER int GetElementOfPoint (const netgen::Point<3> & p,
double * lami,
const NgArray<int> * const indices,
bool build_searchtree = 0,
const bool allowindex = true) const;
DLL_HEADER int GetSurfaceElementOfPoint (const netgen::Point<3> & p,
double * lami,
bool build_searchtree = 0,
const int index = -1,
const bool allowindex = true) const;
DLL_HEADER int GetSurfaceElementOfPoint (const netgen::Point<3> & p,
double * lami,
const NgArray<int> * const indices,
bool build_searchtree = 0,
const bool allowindex = true) const;
DLL_HEADER ElementIndex
GetElementOfPoint (const netgen::Point<3> & p,
double * lami,
bool build_searchtree = false,
int index = -1,
bool allowindex = true) const;
DLL_HEADER ElementIndex
GetElementOfPoint (const netgen::Point<3> & p,
double * lami,
std::optional<FlatArray<int>> indices,
bool build_searchtree = 0,
bool allowindex = true) const;
DLL_HEADER SurfaceElementIndex
GetSurfaceElementOfPoint (const netgen::Point<3> & p,
double * lami,
bool build_searchtree = false,
int index = -1,
bool allowindex = true) const;
DLL_HEADER SurfaceElementIndex
GetSurfaceElementOfPoint (const netgen::Point<3> & p,
double * lami,
std::optional<FlatArray<int>> indices,
bool build_searchtree = false,
bool allowindex = true) const;
/// give list of vol elements which are int the box(p1,p2)
void GetIntersectingVolEls(const Point3d& p1, const Point3d& p2,
NgArray<int> & locels) const;
Array<ElementIndex> & locels) const;
///
int AddFaceDescriptor(const FaceDescriptor& fd)
@ -761,6 +783,15 @@ namespace netgen
std::string_view GetRegionName(SegmentIndex ei) const { return GetRegionName((*this)[ei]); }
std::string_view GetRegionName(SurfaceElementIndex ei) const { return GetRegionName((*this)[ei]); }
std::string_view GetRegionName(ElementIndex ei) const { return GetRegionName((*this)[ei]); }
DLL_HEADER static string_view defaultmat_sv;
std::string_view GetRegionName (int dim, int domnr) // 1-based domnr
{
domnr--;
auto & names = region_name_cd[dimension-dim];
if (domnr < names.Size() && names[domnr]) return *names[domnr];
return defaultmat_sv;
}
///
void ClearFaceDescriptors()
@ -1036,7 +1067,6 @@ namespace netgen
}
DLL_HEADER void AddFacesBetweenDomains(Mesh & mesh);
}
#endif // NETGEN_MESHCLASS_HPP

View File

@ -783,7 +783,7 @@ namespace netgen
free_segs.Append(segi);
auto get_nonconforming = [&] (const auto & p2el) {
Array<size_t> nonconforming;
Array<SegmentIndex> nonconforming;
for (auto segi : free_segs) {
auto seg = mesh[segi];
@ -805,34 +805,29 @@ namespace netgen
auto split_segment = [&] (SegmentIndex segi, const auto & p2el) {
auto seg = mesh[segi];
auto p_new = Center(mesh[seg[0]], mesh[seg[1]]);
auto pi_new = mesh.AddPoint(p_new);
auto seg_new0 = seg;
auto seg_new1 = seg;
seg_new0[1] = pi_new;
seg_new1[0] = pi_new;
mesh[segi][0] = PointIndex::INVALID;
mesh.AddSegment(seg_new0);
mesh.AddSegment(seg_new1);
double lam[3];
ElementIndex ei_start = mesh.GetElementOfPoint(p_new, lam, false, domain);
if(ei_start == 0) {
if(!ei_start.IsValid()) {
PrintMessage(1, "Could not find volume element with new point");
return;
}
ei_start -= 1;
if(mesh[ei_start].IsDeleted())
return;
double max_inside = -1.;
ElementIndex ei_max_inside = -1;
ElementIndex ei_max_inside = ElementIndex::INVALID;
// search for adjacent volume element, where the new point is "most inside",
// i.e. the minimal barycentric coordinate is maximal
for(auto pi : mesh[ei_start].PNums()) {
for(auto ei1 : p2el[pi]) {
double lam[3];
if(!mesh.PointContainedIn3DElement(p_new, lam, ei1+1))
if(mesh[ei1].IsDeleted())
return;
if(!mesh.PointContainedIn3DElement(p_new, lam, ei1))
continue;
double inside = min(min(lam[0], lam[1]), min(lam[2], 1.0-lam[0]-lam[1]));
@ -843,18 +838,34 @@ namespace netgen
}
}
if(max_inside < 1e-4) {
PrintMessage(3, "Could not find volume element with new point inside");
return;
}
// split tet into 4 new tests, with new point inside
auto el = mesh[ei_max_inside];
if(el.GetNP() != 4) {
PrintMessage(1, "Only tet elements are supported to split around free segments");
PrintMessage(3, "Only tet elements are supported to split around free segments");
return;
}
if(el.IsDeleted()) {
PrintMessage(1,"Element to split is already deleted");
PrintMessage(3,"Element to split is already deleted");
return;
}
auto pi_new = mesh.AddPoint(p_new);
auto seg_new0 = seg;
auto seg_new1 = seg;
seg_new0[1] = pi_new;
seg_new1[0] = pi_new;
mesh[segi][0] = PointIndex::INVALID;
mesh.AddSegment(seg_new0);
mesh.AddSegment(seg_new1);
int pmap[4][4] = {
{0,1,2,4},
{1,3,2,4},
@ -897,7 +908,7 @@ namespace netgen
for ([[maybe_unused]] auto i : Range(3)) {
optmesh.ImproveMesh();
optmesh.SwapImprove2 ();
optmesh.SwapImprove2(true);
optmesh.ImproveMesh();
optmesh.SwapImprove();
optmesh.ImproveMesh();
@ -910,7 +921,7 @@ namespace netgen
auto bad_segs = get_nonconforming(p2el);
if(bad_segs.Size() > 0) {
auto bad_seg = mesh[free_segs[bad_segs[0]]];
auto bad_seg = mesh[bad_segs[0]];
if(debugparam.write_mesh_on_error)
mesh.Save("free_segment_not_conformed_dom_"+ToString(domain)+"_seg_"+ToString(bad_seg[0])+"_"+ToString(bad_seg[1])+".vol.gz");
throw Exception("Segment not resolved in volume mesh in domain " + ToString(domain)+ ", seg: " + ToString(bad_seg));

View File

@ -1635,7 +1635,7 @@ namespace netgen
Point<3> pnt;
double h;
int layer = 1;
MeshSizePoint (Point<3> _pnt, double _h) : pnt(_pnt), h(_h) { ; }
MeshSizePoint (Point<3> pnt_, double h_, int layer_ = 1) : pnt(pnt_), h(h_), layer(layer_) { ; }
MeshSizePoint () = default;
MeshSizePoint (const MeshSizePoint &) = default;
MeshSizePoint (MeshSizePoint &&) = default;

View File

@ -966,7 +966,7 @@ namespace netgen
self.ident = make_unique<Identifications> (self);
self.topology = MeshTopology(*this);
self.topology.Update();
self.BuildElementSearchTree();
self.BuildElementSearchTree(3);
// const_cast<Mesh&>(*this).DeleteMesh();

View File

@ -1300,6 +1300,10 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m)
.def("IdentifyPeriodicBoundaries", &Mesh::IdentifyPeriodicBoundaries,
py::arg("identification_name"), py::arg("face1"), py::arg("mapping"),
py::arg("point_tolerance") = -1.)
.def("GetCurveOrder", [] (Mesh & self)
{
return self.GetCurvedElements().GetOrder();
})
.def("GetNrIdentifications", [](Mesh& self)
{
return self.GetIdentifications().GetMaxNr();
@ -1480,7 +1484,8 @@ py::arg("point_tolerance") = -1.)
}))
*/
.def ("BuildSearchTree", &Mesh::BuildElementSearchTree,py::call_guard<py::gil_scoped_release>())
.def ("BuildSearchTree", &Mesh::BuildElementSearchTree,py::call_guard<py::gil_scoped_release>(),
py::arg("dim")=3)
.def ("BoundaryLayer2", GenerateBoundaryLayer2, py::arg("domain"), py::arg("thicknesses"), py::arg("make_new_domain")=true, py::arg("boundaries")=Array<int>{})
.def ("BoundaryLayer", [](Mesh & self, variant<string, int, std::vector<int>> boundary,
@ -1682,25 +1687,25 @@ py::arg("point_tolerance") = -1.)
return mp;
}), py::arg("mp")=nullptr, meshingparameter_description.c_str())
.def("__str__", &ToString<MP>)
.def("RestrictH", [](MP & mp, double x, double y, double z, double h)
.def("RestrictH", [](MP & mp, double x, double y, double z, double h, int layer)
{
mp.meshsize_points.Append ( MeshingParameters::MeshSizePoint(Point<3> (x,y,z), h));
}, py::arg("x"), py::arg("y"), py::arg("z"), py::arg("h")
mp.meshsize_points.Append ( MeshingParameters::MeshSizePoint(Point<3> (x,y,z), h, layer));
}, py::arg("x"), py::arg("y"), py::arg("z"), py::arg("h"), py::arg("layer")=1
)
.def("RestrictH", [](MP & mp, const Point<3>& p, double h)
.def("RestrictH", [](MP & mp, const Point<3>& p, double h, int layer)
{
mp.meshsize_points.Append ({p, h});
}, py::arg("p"), py::arg("h"))
mp.meshsize_points.Append ({p, h, layer});
}, py::arg("p"), py::arg("h"), py::arg("layer")=1)
.def("RestrictHLine", [](MP& mp, const Point<3>& p1, const Point<3>& p2,
double maxh)
double maxh, int layer)
{
int steps = int(Dist(p1, p2) / maxh) + 2;
auto v = p2 - p1;
for (int i = 0; i <= steps; i++)
{
mp.meshsize_points.Append({p1 + double(i)/steps * v, maxh});
mp.meshsize_points.Append({p1 + double(i)/steps * v, maxh, layer});
}
}, py::arg("p1"), py::arg("p2"), py::arg("maxh"))
}, py::arg("p1"), py::arg("p2"), py::arg("maxh"), py::arg("layer")=1)
;
m.def("SetTestoutFile", FunctionPointer ([] (const string & filename)

View File

@ -2288,10 +2288,22 @@ namespace netgen
XCAFPrs::CollectStyleSettings(label, loc, set);
XCAFPrs_Style aStyle;
set.FindFromKey(e.Current(), aStyle);
auto & prop = OCCGeometry::GetProperties(e.Current());
if(aStyle.IsSetColorSurf())
prop.col = step_utils::ReadColor(aStyle.GetColorSurfRGBA());
{
for(TopExp_Explorer e2(e.Current(), TopAbs_FACE); e2.More(); e2.Next())
{
auto & prop = OCCGeometry::GetProperties(e2.Current());
prop.col = step_utils::ReadColor(aStyle.GetColorSurfRGBA());
}
}
if(aStyle.IsSetColorCurv())
{
for(TopExp_Explorer e2(e.Current(), TopAbs_EDGE); e2.More(); e2.Next())
{
auto & prop = OCCGeometry::GetProperties(e2.Current());
prop.col = step_utils::ReadColor(aStyle.GetColorSurfRGBA());
}
}
}
// load names

View File

@ -21,6 +21,9 @@
#include <XCAFDoc_DocumentTool.hxx>
#include <XCAFDoc_MaterialTool.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <TopoDS_Edge.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <GCPnts_TangentialDeflection.hxx>
using namespace netgen;
@ -165,10 +168,40 @@ DLL_HEADER void ExportNgOCC(py::module &m)
{
ng_geometry = geo;
})
.def_property_readonly("solids", [](shared_ptr<OCCGeometry> geo)
{
ListOfShapes solids;
for (int i = 1; i <= geo->somap.Extent(); i++)
solids.push_back(geo->somap(i));
return solids;
}, "Get solids in order that they will be in the mesh")
.def_property_readonly("faces", [](shared_ptr<OCCGeometry> geo)
{
ListOfShapes faces;
for (int i = 1; i <= geo->fmap.Extent(); i++)
faces.push_back(geo->fmap(i));
return faces;
}, "Get faces in order that they will be in the mesh")
.def_property_readonly("edges", [](shared_ptr<OCCGeometry> geo)
{
ListOfShapes edges;
for (int i = 1; i <= geo->emap.Extent(); i++)
edges.push_back(geo->emap(i));
return edges;
}, "Get edges in order that they will be in the mesh")
.def_property_readonly("vertices", [](shared_ptr<OCCGeometry> geo)
{
ListOfShapes vertices;
for (int i = 1; i <= geo->vmap.Extent(); i++)
vertices.push_back(geo->vmap(i));
return vertices;
}, "Get vertices in order that they will be in the mesh")
.def("_visualizationData", [] (shared_ptr<OCCGeometry> occ_geo)
{
std::vector<float> vertices;
std::vector<int> trigs;
std::vector<uint32_t> indices;
std::vector<float> edges;
std::vector<uint32_t> edge_indices;
std::vector<float> normals;
std::vector<float> min = {std::numeric_limits<float>::max(),
std::numeric_limits<float>::max(),
@ -176,7 +209,8 @@ DLL_HEADER void ExportNgOCC(py::module &m)
std::vector<float> max = {std::numeric_limits<float>::lowest(),
std::numeric_limits<float>::lowest(),
std::numeric_limits<float>::lowest()};
std::vector<string> surfnames;
std::vector<float> face_colors;
std::vector<float> edge_colors;
auto box = occ_geo->GetBoundingBox();
for(int i = 0; i < 3; i++)
{
@ -188,11 +222,67 @@ DLL_HEADER void ExportNgOCC(py::module &m)
gp_Pnt pnt;
gp_Vec n;
gp_Pnt p[3];
int count = 0;
for(int edge_index = 1; edge_index <= occ_geo->emap.Extent();
edge_index++)
{
auto edge = TopoDS::Edge(occ_geo->emap(edge_index));
if(OCCGeometry::HaveProperties(edge))
{
const auto& props = OCCGeometry::GetProperties(edge);
if(props.col)
edge_colors.insert(edge_colors.end(),
{float((*props.col)[0]),
float((*props.col)[1]),
float((*props.col)[2]),
float((*props.col)[3])});
else
edge_colors.insert(edge_colors.end(),{0.f,0.f,0.f,1.f});
}
else
{
edge_colors.insert(edge_colors.end(),{0.f,0.f,0.f,1.f});
}
BRepAdaptor_Curve adapt_crv = BRepAdaptor_Curve(edge);
GCPnts_TangentialDeflection discretizer;
discretizer.Initialize(adapt_crv, 0.09, 0.01);
if (discretizer.NbPoints() > 1)
{
for (int j = 1; j <= discretizer.NbPoints()-1; ++j)
{
gp_Pnt p_0 = discretizer.Value(j);
gp_Pnt p_1 = discretizer.Value(j+1);
edges.insert(edges.end(),
{float(p_0.X()),
float(p_0.Y()),
float(p_0.Z()),
float(p_1.X()),
float(p_1.Y()),
float(p_1.Z())});
edge_indices.push_back(uint32_t(edge_index-1));
}
}
}
for (int i = 1; i <= occ_geo->fmap.Extent(); i++)
{
surfnames.push_back("occ_surface" + to_string(i));
auto face = TopoDS::Face(occ_geo->fmap(i));
if (OCCGeometry::HaveProperties(face))
{
const auto& props = OCCGeometry::GetProperties(face);
if(props.col)
face_colors.insert(face_colors.end(),
{float((*props.col)[0]),
float((*props.col)[1]),
float((*props.col)[2]),
float((*props.col)[3])});
else
{
face_colors.insert(face_colors.end(),{0.7,0.7,0.7,1.});
}
}
else
{
face_colors.insert(face_colors.end(),{0.7,0.7,0.7,1.});
}
auto surf = BRep_Tool::Surface(face);
TopLoc_Location loc;
BRepAdaptor_Surface sf(face, Standard_False);
@ -200,7 +290,7 @@ DLL_HEADER void ExportNgOCC(py::module &m)
Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc);
if (triangulation.IsNull())
cout << "cannot visualize face " << i << endl;
trigs.reserve(trigs.size() + triangulation->NbTriangles()*4);
indices.reserve(indices.size() + triangulation->NbTriangles());
vertices.reserve(vertices.size() + triangulation->NbTriangles()*3*3);
normals.reserve(normals.size() + triangulation->NbTriangles()*3*3);
for (int j = 1; j < triangulation->NbTriangles()+1; j++)
@ -208,11 +298,13 @@ DLL_HEADER void ExportNgOCC(py::module &m)
auto triangle = triangulation->Triangle(j);
for (int k = 1; k < 4; k++)
p[k-1] = triangulation->Node(triangle(k)).Transformed(loc);
indices.push_back(uint32_t(i-1));
for (int k = 1; k < 4; k++)
{
vertices.insert(vertices.end(),{float(p[k-1].X()), float(p[k-1].Y()), float(p[k-1].Z())});
trigs.insert(trigs.end(),{count, count+1, count+2,i});
count += 3;
vertices.insert(vertices.end(),{
float(p[k-1].X()),
float(p[k-1].Y()),
float(p[k-1].Z())});
uv = triangulation->UVNode(triangle(k));
prop.SetParameters(uv.X(), uv.Y());
if (prop.IsNormalDefined())
@ -231,12 +323,13 @@ DLL_HEADER void ExportNgOCC(py::module &m)
py::gil_scoped_acquire ac;
py::dict res;
py::list snames;
for(auto name : surfnames)
snames.append(py::cast(name));
res["vertices"] = MoveToNumpy(vertices);
res["triangles"] = MoveToNumpy(trigs);
res["edges"] = MoveToNumpy(edges);
res["edge_indices"] = MoveToNumpy(edge_indices);
res["edge_colors"] = MoveToNumpy(edge_colors);
res["indices"] = MoveToNumpy(indices);
res["normals"] = MoveToNumpy(normals);
res["surfnames"] = snames;
res["face_colors"] = MoveToNumpy(face_colors);
res["min"] = MoveToNumpy(min);
res["max"] = MoveToNumpy(max);
return res;

View File

@ -14,6 +14,9 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#if OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=6
#include <BinTools_ShapeWriter.hxx>
#endif // OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=4
#include <BOPAlgo_Builder.hxx>
#include <BOPTools_AlgoTools.hxx>
#include <BRepAlgoAPI_Common.hxx>
@ -49,6 +52,7 @@
#include <BRepTools.hxx>
#include <GCE2d_MakeArcOfCircle.hxx>
#include <GCE2d_MakeCircle.hxx>
#include <GCE2d_MakeEllipse.hxx>
#include <GCE2d_MakeSegment.hxx>
#include <GC_MakeArcOfCircle.hxx>
#include <GC_MakeCircle.hxx>
@ -598,6 +602,19 @@ public:
return shared_from_this();
}
auto Ellipse(double major, double minor)
{
Handle(Geom2d_Ellipse) ell_curve = GCE2d_MakeEllipse(localpos, major, minor).Value();
auto edge = BRepBuilderAPI_MakeEdge(ell_curve, surf).Edge();
BRepLib::BuildCurves3d(edge);
wire_builder.Add(edge);
wires.push_back (wire_builder.Wire());
wire_builder = BRepBuilderAPI_MakeWire();
return shared_from_this();
}
auto NameVertex (string name)
{
if (!lastvertex.IsNull())
@ -689,6 +706,32 @@ DLL_HEADER void ExportNgOCCShapes(py::module &m)
OCCGeometry::global_shape_properties.clear();
OCCGeometry::global_shape_property_indices.Clear();
});
struct SwigTypeInfo
{
const char* name; // SWIG's type name string
// Other fields...
};
struct SwigPyObject{
PyObject_HEAD
void *ptr;
SwigTypeInfo* ty; // SWIG type information
int own; // ownership flag
};
m.def("From_PyOCC", [](py::object shape)
{
py::object py_this = shape.attr("this");
PyObject* obj = py_this.ptr();
SwigPyObject* swig_obj = reinterpret_cast<SwigPyObject*>(obj);
if (!swig_obj->ptr || !swig_obj->ty || !swig_obj->ty->name) {
throw std::runtime_error("SWIG object does not contain a valid pointer");
}
if(strcmp(swig_obj->ty->name, "_p_TopoDS_Shape") != 0)
throw std::runtime_error("Does not contain TopoDS_Shape from pyocc!");
return py::cast(static_cast<TopoDS_Shape*>(swig_obj->ptr));
}, py::return_value_policy::reference, py::keep_alive<0,1>());
py::class_<TopoDS_Shape> (m, "TopoDS_Shape")
.def("__str__", [] (const TopoDS_Shape & shape)
@ -807,10 +850,33 @@ DLL_HEADER void ExportNgOCCShapes(py::module &m)
.def("WriteStep", [](const TopoDS_Shape & shape, string & filename)
{ step_utils::WriteSTEP(shape, filename); }
, py::arg("filename"), "export shape in STEP - format")
.def("WriteBrep", [](const TopoDS_Shape & shape, const string& filename)
.def("WriteBrep", [](const TopoDS_Shape & shape, const string& filename,
bool withTriangles, bool withNormals,
optional<int> version, bool binary)
{
BRepTools::Write(shape, filename.c_str());
}, py::arg("filename"), "export shape in BREP - format")
if(binary)
{
#if OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=6
BinTools_FormatVersion v = version ? BinTools_FormatVersion(*version) : BinTools_FormatVersion_CURRENT;
BinTools::Write(shape, filename.c_str(), withTriangles, withNormals, v);
# else // OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=6
throw Exception("Binary BREP export not supported in this version of OpenCascade");
#endif // OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=6
}
else
{
#if OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=6
TopTools_FormatVersion v = version ? (TopTools_FormatVersion)(*version) : TopTools_FormatVersion_CURRENT;
BRepTools::Write(shape, filename.c_str(), withTriangles, withNormals, v);
#else // OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=6
BRepTools::Write(shape, filename.c_str());
#endif // OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=6
}
}, py::arg("filename"), py::arg("withTriangles")=true,
py::arg("withNormals")=false,
py::arg("version")=py::none(),
py::arg("binary")=false,
"export shape in BREP - format")
.def("bc", [](const TopoDS_Shape & shape, const string & name)
{
for (TopExp_Explorer e(shape, TopAbs_FACE); e.More(); e.Next())
@ -1898,21 +1964,21 @@ DLL_HEADER void ExportNgOCCShapes(py::module &m)
})
.def("Edge", [](Handle(Geom2d_Curve) curve) {
// static Geom_Plane surf{gp_Ax3()}; // crashes in nbconvert ???
static auto surf = new Geom_Plane{gp_Ax3()};
static auto surf = Handle(Geom_Plane)(new Geom_Plane{gp_Ax3()});
auto edge = BRepBuilderAPI_MakeEdge(curve, surf).Edge();
BRepLib::BuildCurves3d(edge);
return edge;
})
.def("Wire", [](Handle(Geom2d_Curve) curve) {
// static Geom_Plane surf{gp_Ax3()}; // crashes in nbconvert ???
static auto surf = new Geom_Plane{gp_Ax3()};
static auto surf = Handle(Geom_Plane)(new Geom_Plane{gp_Ax3()});
auto edge = BRepBuilderAPI_MakeEdge(curve, surf).Edge();
BRepLib::BuildCurves3d(edge);
return BRepBuilderAPI_MakeWire(edge).Wire();
})
.def("Face", [](Handle(Geom2d_Curve) curve) {
// static Geom_Plane surf{gp_Ax3()}; // crashes in nbconvert ???
static auto surf = new Geom_Plane{gp_Ax3()};
static auto surf = Handle(Geom_Plane)(new Geom_Plane{gp_Ax3()});
auto edge = BRepBuilderAPI_MakeEdge(curve, surf).Edge();
BRepLib::BuildCurves3d(edge);
auto wire = BRepBuilderAPI_MakeWire(edge).Wire();
@ -2046,14 +2112,19 @@ DLL_HEADER void ExportNgOCCShapes(py::module &m)
return BRepOffsetAPI_MakePipe (spine, profile).Shape();
}, py::arg("spine"), py::arg("profile"), py::arg("twist")=nullopt, py::arg("auxspine")=nullopt);
m.def("PipeShell", [] (const TopoDS_Wire & spine, const TopoDS_Shape & profile, const TopoDS_Wire & auxspine) {
m.def("PipeShell", [] (const TopoDS_Wire & spine, variant<TopoDS_Shape, std::vector<TopoDS_Shape>> profile, std::optional<TopoDS_Wire> auxspine) {
try
{
BRepOffsetAPI_MakePipeShell builder(spine);
builder.SetMode (auxspine, Standard_True);
builder.Add (profile);
// builder.Build();
// builder.MakeSolid();
if(auxspine)
builder.SetMode (*auxspine, Standard_True);
if(std::holds_alternative<TopoDS_Shape>(profile))
builder.Add (std::get<TopoDS_Shape>(profile));
else
{
for(auto s : std::get<std::vector<TopoDS_Shape>>(profile))
builder.Add(s);
}
return builder.Shape();
}
catch (Standard_Failure & e)
@ -2062,13 +2133,13 @@ DLL_HEADER void ExportNgOCCShapes(py::module &m)
e.Print(errstr);
throw NgException("cannot create PipeShell: "+errstr.str());
}
}, py::arg("spine"), py::arg("profile"), py::arg("auxspine"));
}, py::arg("spine"), py::arg("profile"), py::arg("auxspine")=nullopt);
// Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor);
m.def("Ellipse", [] (const gp_Ax2d & ax, double major, double minor) -> Handle(Geom2d_Curve)
{
return new Geom2d_Ellipse(ax, major, minor);
return Handle(Geom2d_Ellipse) (GCE2d_MakeEllipse(ax, major, minor));
}, py::arg("axes"), py::arg("major"), py::arg("minor"), "create 2d ellipse curve");
m.def("Segment", [](gp_Pnt2d p1, gp_Pnt2d p2) -> Handle(Geom2d_Curve) {
@ -2636,6 +2707,8 @@ degen_tol : double
.def("Circle", [](WorkPlane&wp, double x, double y, double r) {
return wp.Circle(x,y,r); }, py::arg("h"), py::arg("v"), py::arg("r"), "draw circle with center (h,v) and radius 'r'")
.def("Circle", [](WorkPlane&wp, double r) { return wp.Circle(r); }, py::arg("r"), "draw circle with center in current position")
.def("Ellipse", [](WorkPlane& wp, double major, double minor)
{ return wp.Ellipse(major, minor); }, py::arg("major"), py::arg("minor"), "draw ellipse with current position as center")
.def("NameVertex", &WorkPlane::NameVertex, py::arg("name"), "name vertex at current position")
.def("Offset", &WorkPlane::Offset, py::arg("d"), "replace current wire by offset curve of distance 'd'")
.def("Reverse", &WorkPlane::Reverse, "revert orientation of current wire")

View File

@ -57,6 +57,13 @@ namespace netgen
return opengl_text_width;
}
void MyOpenGLLines(FlatArray<Point<3>> points)
{
glBegin(GL_LINES);
for (auto p : points)
glVertex3dv(&p[0]);
glEnd();
}
// texture for color decoding
// GLubyte * VisualScene :: colortexture = NULL;

View File

@ -90,6 +90,7 @@ namespace netgen
NGGUI_API extern void Set_OpenGLText_Callback ( void (*fun) (const char * text), int width );
NGGUI_API extern VisualScene visual_scene_cross;
NGGUI_API extern VisualScene *visual_scene;
NGGUI_API extern void MyOpenGLLines (FlatArray<Point<3>> points);

View File

@ -841,7 +841,7 @@ namespace netgen
if (vispar.clipping.enable && clipsolution == 2)
{
mesh->Mutex().unlock();
mesh->BuildElementSearchTree();
mesh->BuildElementSearchTree(3);
mesh->Mutex().lock();
}
@ -2667,6 +2667,8 @@ namespace netgen
for (int i=first; i<next; i++)
{
double val;
if(!VolumeElementActive(sol, *mesh, (*mesh)[ElementIndex(i)]))
continue;
bool considerElem = GetValue (sol, i, 0.333, 0.333, 0.333, comp, val);
if (considerElem)
{
@ -2698,6 +2700,8 @@ namespace netgen
// for (int i = 0; i < nse; i++)
for (SurfaceElementIndex i : mesh->SurfaceElements().Range())
{
if(!SurfaceElementActive(sol, *mesh, (*mesh)[i]))
continue;
ELEMENT_TYPE type = (*mesh)[i].GetType();
double val;
bool considerElem = (type == QUAD)
@ -4337,7 +4341,7 @@ namespace netgen
}
double lami[3];
int elnr = mesh->GetElementOfPoint (hp, lami,0,cindex,allowindex)-1;
int elnr = mesh->GetElementOfPoint (hp, lami,0,cindex,allowindex);
if (elnr != -1)
{
@ -4723,7 +4727,7 @@ namespace netgen
bool VisualSceneSolution ::
SurfaceElementActive(const SolData *data, const Mesh & mesh, const Element2d & el)
SurfaceElementActive(const SolData *data, const Mesh & mesh, const Element2d & el) const
{
if(data == nullptr) return true;
bool is_active = true;
@ -4749,7 +4753,7 @@ namespace netgen
}
bool VisualSceneSolution ::
VolumeElementActive(const SolData *data, const Mesh & mesh, const Element & el)
VolumeElementActive(const SolData *data, const Mesh & mesh, const Element & el) const
{
bool is_active = true;
if(data->draw_volumes)
@ -4858,18 +4862,18 @@ namespace netgen
if(sol.iscomplex && rcomponent != 0)
{
rcomponent = 2 * ((rcomponent-1)/2) + 1;
GetValue(&sol, el3d-1, lami[0], lami[1], lami[2], rcomponent+1,
GetValue(&sol, el3d, lami[0], lami[1], lami[2], rcomponent+1,
imag);
comp = (scalcomp-1)/2 + 1;
}
GetValue(&sol, el3d-1, lami[0], lami[1], lami[2], rcomponent, val);
GetValue(&sol, el3d, lami[0], lami[1], lami[2], rcomponent, val);
printScalValue(sol, comp, val, imag, sol.iscomplex && comp > 0);
}
if(vecfunction!=-1 && soldata[vecfunction]->draw_volume)
{
auto & sol = *soldata[vecfunction];
ArrayMem<double, 10> values(sol.components);
GetValues(&sol, el3d-1, lami[0], lami[1], lami[2], &values[0]);
GetValues(&sol, el3d, lami[0], lami[1], lami[2], &values[0]);
printVecValue(sol, values);
}
return;
@ -4880,7 +4884,7 @@ namespace netgen
double lami[3] = {0.0, 0.0, 0.0};
// Check if unprojected Point is close to surface element (eps of 1e-3 due to z-Buffer accuracy)
bool found_2del = false;
if(selelement>0 && mesh->PointContainedIn2DElement(p, lami, selelement, false && fabs(lami[2])<1e-3))
if(selelement>0 && mesh->PointContainedIn2DElement(p, lami, selelement-1, false && fabs(lami[2])<1e-3))
{
// Found it, use coordinates of point projected to surface element
mesh->GetCurvedElements().CalcSurfaceTransformation({1.0-lami[0]-lami[1], lami[0]}, selelement-1, p);

View File

@ -253,8 +253,8 @@ private:
void DrawCone (const Point<3> & p1, const Point<3> & p2, double r);
void DrawCylinder (const Point<3> & p1, const Point<3> & p2, double r);
bool SurfaceElementActive(const SolData *data, const Mesh & mesh, const Element2d & sei);
bool VolumeElementActive(const SolData *data, const Mesh & mesh, const Element & ei);
bool SurfaceElementActive(const SolData *data, const Mesh & mesh, const Element2d & sei) const;
bool VolumeElementActive(const SolData *data, const Mesh & mesh, const Element & ei) const;
// Get Function Value, local coordinates lam1, lam2, lam3,
bool GetValue (const SolData * data, ElementIndex elnr,