Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
O
ogs
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Yuhao Liu
ogs
Commits
b97dba8a
Commit
b97dba8a
authored
9 years ago
by
Tom Fischer
Browse files
Options
Downloads
Patches
Plain Diff
[MeL/MS] Initial impl. of MeshElementGrid.
parent
d0071a08
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
MeshLib/MeshSearch/MeshElementGrid.cpp
+262
-0
262 additions, 0 deletions
MeshLib/MeshSearch/MeshElementGrid.cpp
MeshLib/MeshSearch/MeshElementGrid.h
+120
-0
120 additions, 0 deletions
MeshLib/MeshSearch/MeshElementGrid.h
with
382 additions
and
0 deletions
MeshLib/MeshSearch/MeshElementGrid.cpp
0 → 100644
+
262
−
0
View file @
b97dba8a
/*
* \brief Definition of the class MeshElementGrid.
*
* \copyright
* Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
*/
#include
"MeshElementGrid.h"
#include
<algorithm>
#include
<bitset>
#include
<cmath>
#include
<memory>
#include
<logog/include/logog.hpp>
#include
"../Mesh.h"
#include
"../Node.h"
#include
"../Elements/Element.h"
#include
"GeoLib/GEOObjects.h"
namespace
MeshLib
{
MeshElementGrid
::
MeshElementGrid
(
MeshLib
::
Mesh
const
&
sfc_mesh
)
:
_aabb
{
sfc_mesh
.
getNodes
().
cbegin
(),
sfc_mesh
.
getNodes
().
cend
()},
_n_steps
({{
1
,
1
,
1
}})
{
auto
getDimensions
=
[](
MathLib
::
Point3d
const
&
min
,
MathLib
::
Point3d
const
&
max
)
{
std
::
bitset
<
3
>
dim
;
// all bits are set to zero.
for
(
std
::
size_t
k
(
0
);
k
<
3
;
++
k
)
{
double
const
tolerance
(
std
::
nexttoward
(
max
[
k
],
std
::
numeric_limits
<
double
>::
max
())
-
max
[
k
]);
if
(
std
::
abs
(
max
[
k
]
-
min
[
k
])
>
tolerance
)
dim
[
k
]
=
true
;
}
return
dim
;
};
MathLib
::
Point3d
const
&
min_pnt
(
_aabb
.
getMinPoint
());
MathLib
::
Point3d
const
&
max_pnt
(
_aabb
.
getMaxPoint
());
auto
const
dim
=
getDimensions
(
min_pnt
,
max_pnt
);
std
::
array
<
double
,
3
>
delta
{{
max_pnt
[
0
]
-
min_pnt
[
0
],
max_pnt
[
1
]
-
min_pnt
[
1
],
max_pnt
[
2
]
-
min_pnt
[
2
]
}};
const
std
::
size_t
n_eles
(
sfc_mesh
.
getNElements
());
const
std
::
size_t
n_eles_per_cell
(
100
);
// *** condition: n_eles / n_cells < n_eles_per_cell
// where n_cells = _n_steps[0] * _n_steps[1] * _n_steps[2]
// *** with _n_steps[0] = ceil(pow(n_eles*delta[0]*delta[0]/(n_eles_per_cell*delta[1]*delta[2]), 1/3.)));
// _n_steps[1] = _n_steps[0] * delta[1]/delta[0],
// _n_steps[2] = _n_steps[0] * delta[2]/delta[0]
auto
sc_ceil
=
[](
double
v
){
return
static_cast
<
std
::
size_t
>
(
std
::
ceil
(
v
));
};
switch
(
dim
.
count
())
{
case
3
:
// 3d case
_n_steps
[
0
]
=
sc_ceil
(
std
::
cbrt
(
n_eles
*
delta
[
0
]
*
delta
[
0
]
/
(
n_eles_per_cell
*
delta
[
1
]
*
delta
[
2
])));
_n_steps
[
1
]
=
sc_ceil
(
_n_steps
[
0
]
*
std
::
min
(
delta
[
1
]
/
delta
[
0
],
100.0
));
_n_steps
[
2
]
=
sc_ceil
(
_n_steps
[
0
]
*
std
::
min
(
delta
[
2
]
/
delta
[
0
],
100.0
));
break
;
case
2
:
// 2d cases
if
(
dim
[
0
]
&&
dim
[
2
])
{
// 2d case: xz plane, y = const
_n_steps
[
0
]
=
sc_ceil
(
std
::
sqrt
(
n_eles
*
delta
[
0
]
/
(
n_eles_per_cell
*
delta
[
2
])));
_n_steps
[
2
]
=
sc_ceil
(
_n_steps
[
0
]
*
delta
[
2
]
/
delta
[
0
]);
}
else
if
(
dim
[
0
]
&&
dim
[
1
])
{
// 2d case: xy plane, z = const
_n_steps
[
0
]
=
sc_ceil
(
std
::
sqrt
(
n_eles
*
delta
[
0
]
/
(
n_eles_per_cell
*
delta
[
1
])));
_n_steps
[
1
]
=
sc_ceil
(
_n_steps
[
0
]
*
delta
[
1
]
/
delta
[
0
]);
}
else
if
(
dim
[
1
]
&&
dim
[
2
])
{
// 2d case: yz plane, x = const
_n_steps
[
1
]
=
sc_ceil
(
std
::
sqrt
(
n_eles
*
delta
[
1
]
/
(
n_eles_per_cell
*
delta
[
2
])));
_n_steps
[
2
]
=
sc_ceil
(
n_eles
*
delta
[
2
]
/
(
n_eles_per_cell
*
delta
[
1
]));
}
break
;
case
1
:
// 1d cases
for
(
std
::
size_t
k
(
0
);
k
<
3
;
++
k
)
{
if
(
dim
[
k
])
{
_n_steps
[
k
]
=
sc_ceil
(
static_cast
<
double
>
(
n_eles
)
/
n_eles_per_cell
);
}
}
}
// some frequently used expressions to fill the vector of elements per grid
// cell
for
(
std
::
size_t
k
(
0
);
k
<
3
;
k
++
)
{
_step_sizes
[
k
]
=
delta
[
k
]
/
_n_steps
[
k
];
_inverse_step_sizes
[
k
]
=
1.0
/
_step_sizes
[
k
];
}
_elements_in_grid_box
.
resize
(
_n_steps
[
0
]
*
_n_steps
[
1
]
*
_n_steps
[
2
]);
sortElementsInGridCells
(
sfc_mesh
);
}
void
MeshElementGrid
::
sortElementsInGridCells
(
MeshLib
::
Mesh
const
&
sfc_mesh
)
{
for
(
auto
const
element
:
sfc_mesh
.
getElements
())
{
if
(
!
sortElementInGridCells
(
*
element
))
{
ERR
(
"Fatal error: Sorting element (id=%d) into mesh element grid."
,
element
->
getID
());
std
::
abort
();
}
}
}
bool
MeshElementGrid
::
sortElementInGridCells
(
MeshLib
::
Element
const
&
element
)
{
std
::
array
<
std
::
size_t
,
3
>
min
;
std
::
array
<
std
::
size_t
,
3
>
max
;
std
::
pair
<
bool
,
std
::
array
<
std
::
size_t
,
3
>>
c
(
getGridCellCoordinates
(
*
(
static_cast
<
MathLib
::
Point3d
const
*>
(
element
.
getNode
(
0
)))));
if
(
c
.
first
)
{
min
=
c
.
second
;
max
=
min
;
}
else
{
return
false
;
}
std
::
vector
<
std
::
array
<
std
::
size_t
,
3
>>
coord_vecs
(
element
.
getNNodes
());
for
(
std
::
size_t
k
(
1
);
k
<
element
.
getNNodes
();
++
k
)
{
// compute coordinates of the grid for each node of the element
c
=
getGridCellCoordinates
(
*
(
static_cast
<
MathLib
::
Point3d
const
*>
(
element
.
getNode
(
k
))));
if
(
!
c
.
first
)
return
false
;
else
{
for
(
std
::
size_t
j
(
0
);
j
<
3
;
++
j
)
{
if
(
min
[
j
]
>
c
.
second
[
j
])
min
[
j
]
=
c
.
second
[
j
];
if
(
max
[
j
]
<
c
.
second
[
j
])
max
[
j
]
=
c
.
second
[
j
];
}
}
}
const
std
::
size_t
n_plane
(
_n_steps
[
0
]
*
_n_steps
[
1
]);
// insert the element into the grid cells
for
(
std
::
size_t
i
(
min
[
0
]);
i
<=
max
[
0
];
i
++
)
{
for
(
std
::
size_t
j
(
min
[
1
]);
j
<=
max
[
1
];
j
++
)
{
for
(
std
::
size_t
k
(
min
[
2
]);
k
<=
max
[
2
];
k
++
)
{
_elements_in_grid_box
[
i
+
j
*
_n_steps
[
0
]
+
k
*
n_plane
].
push_back
(
&
element
);
}
}
}
return
true
;
}
std
::
pair
<
bool
,
std
::
array
<
std
::
size_t
,
3
>>
MeshElementGrid
::
getGridCellCoordinates
(
MathLib
::
Point3d
const
&
p
)
const
{
bool
valid
(
true
);
std
::
array
<
std
::
size_t
,
3
>
coords
;
for
(
std
::
size_t
k
(
0
);
k
<
3
;
++
k
)
{
const
double
d
(
p
[
k
]
-
_aabb
.
getMinPoint
()[
k
]);
if
(
d
<
0.0
)
{
valid
=
false
;
coords
[
k
]
=
0
;
}
else
if
(
_aabb
.
getMaxPoint
()[
k
]
<=
p
[
k
])
{
valid
=
false
;
coords
[
k
]
=
_n_steps
[
k
]
-
1
;
}
else
{
coords
[
k
]
=
static_cast
<
std
::
size_t
>
(
d
*
_inverse_step_sizes
[
k
]);
}
}
return
std
::
make_pair
(
valid
,
coords
);
}
#ifndef NDEBUG
void
getGridGeometry
(
MeshElementGrid
const
&
grid
,
GeoLib
::
GEOObjects
&
geometries
,
std
::
string
&
geometry_name
)
{
std
::
vector
<
std
::
string
>
cell_names
;
auto
addPoints
=
[
&
geometries
](
MathLib
::
Point3d
const
&
p
,
std
::
array
<
double
,
3
>
const
&
d
,
std
::
array
<
std
::
size_t
,
3
>
const
&
c
,
std
::
string
&
name
)
{
auto
pnts
=
std
::
unique_ptr
<
std
::
vector
<
GeoLib
::
Point
*>>
(
new
std
::
vector
<
GeoLib
::
Point
*>
);
pnts
->
push_back
(
new
GeoLib
::
Point
(
p
[
0
]
+
c
[
0
]
*
d
[
0
],
p
[
1
]
+
c
[
1
]
*
d
[
1
],
p
[
2
]
+
c
[
2
]
*
d
[
2
]));
pnts
->
push_back
(
new
GeoLib
::
Point
(
p
[
0
]
+
c
[
0
]
*
d
[
0
],
p
[
1
]
+
(
c
[
1
]
+
1
)
*
d
[
1
],
p
[
2
]
+
c
[
2
]
*
d
[
2
]));
pnts
->
push_back
(
new
GeoLib
::
Point
(
p
[
0
]
+
(
c
[
0
]
+
1
)
*
d
[
0
],
p
[
1
]
+
(
c
[
1
]
+
1
)
*
d
[
1
],
p
[
2
]
+
c
[
2
]
*
d
[
2
]));
pnts
->
push_back
(
new
GeoLib
::
Point
(
p
[
0
]
+
(
c
[
0
]
+
1
)
*
d
[
0
],
p
[
1
]
+
c
[
1
]
*
d
[
1
],
p
[
2
]
+
c
[
2
]
*
d
[
2
]));
pnts
->
push_back
(
new
GeoLib
::
Point
(
p
[
0
]
+
c
[
0
]
*
d
[
0
],
p
[
1
]
+
c
[
1
]
*
d
[
1
],
p
[
2
]
+
(
c
[
2
]
+
1
)
*
d
[
2
]));
pnts
->
push_back
(
new
GeoLib
::
Point
(
p
[
0
]
+
c
[
0
]
*
d
[
0
],
p
[
1
]
+
(
c
[
1
]
+
1
)
*
d
[
1
],
p
[
2
]
+
(
c
[
2
]
+
1
)
*
d
[
2
]));
pnts
->
push_back
(
new
GeoLib
::
Point
(
p
[
0
]
+
(
c
[
0
]
+
1
)
*
d
[
0
],
p
[
1
]
+
(
c
[
1
]
+
1
)
*
d
[
1
],
p
[
2
]
+
(
c
[
2
]
+
1
)
*
d
[
2
]));
pnts
->
push_back
(
new
GeoLib
::
Point
(
p
[
0
]
+
(
c
[
0
]
+
1
)
*
d
[
0
],
p
[
1
]
+
c
[
1
]
*
d
[
1
],
p
[
2
]
+
(
c
[
2
]
+
1
)
*
d
[
2
]));
std
::
array
<
double
,
3
>
ulps
;
// unit in the last place
double
const
towards
(
std
::
numeric_limits
<
double
>::
max
());
ulps
[
0
]
=
std
::
nextafter
(
d
[
0
],
towards
)
-
d
[
0
];
ulps
[
1
]
=
std
::
nextafter
(
d
[
1
],
towards
)
-
d
[
1
];
ulps
[
2
]
=
std
::
nextafter
(
d
[
2
],
towards
)
-
d
[
2
];
double
const
tolerance
(
std
::
min
(
std
::
min
(
ulps
[
0
],
ulps
[
1
]),
ulps
[
2
]));
geometries
.
addPointVec
(
std
::
move
(
pnts
),
name
,
nullptr
,
tolerance
);
};
for
(
std
::
size_t
i
(
0
);
i
<
grid
.
_n_steps
[
0
];
++
i
)
{
for
(
std
::
size_t
j
(
0
);
j
<
grid
.
_n_steps
[
1
];
++
j
)
{
for
(
std
::
size_t
k
(
0
);
k
<
grid
.
_n_steps
[
2
];
++
k
)
{
cell_names
.
emplace_back
(
"Grid-"
+
std
::
to_string
(
i
)
+
"-"
+
std
::
to_string
(
j
)
+
"-"
+
std
::
to_string
(
k
));
addPoints
(
grid
.
_aabb
.
getMinPoint
(),
grid
.
_step_sizes
,
{{
i
,
j
,
k
}},
cell_names
.
back
());
auto
plys
=
std
::
unique_ptr
<
std
::
vector
<
GeoLib
::
Polyline
*>>
(
new
std
::
vector
<
GeoLib
::
Polyline
*>
);
auto
&
points
=
*
geometries
.
getPointVec
(
cell_names
.
back
());
GeoLib
::
Polyline
*
ply_bottom
(
new
GeoLib
::
Polyline
(
points
));
for
(
std
::
size_t
l
(
0
);
l
<
4
;
++
l
)
ply_bottom
->
addPoint
(
l
);
ply_bottom
->
addPoint
(
0
);
// close to bottom surface
plys
->
push_back
(
ply_bottom
);
GeoLib
::
Polyline
*
ply_top
(
new
GeoLib
::
Polyline
(
points
));
for
(
std
::
size_t
l
(
4
);
l
<
8
;
++
l
)
ply_top
->
addPoint
(
l
);
ply_top
->
addPoint
(
4
);
// close to top surface
plys
->
push_back
(
ply_top
);
GeoLib
::
Polyline
*
ply_04
(
new
GeoLib
::
Polyline
(
points
));
ply_04
->
addPoint
(
0
);
ply_04
->
addPoint
(
4
);
plys
->
push_back
(
ply_04
);
GeoLib
::
Polyline
*
ply_15
(
new
GeoLib
::
Polyline
(
points
));
ply_15
->
addPoint
(
1
);
ply_15
->
addPoint
(
5
);
plys
->
push_back
(
ply_15
);
GeoLib
::
Polyline
*
ply_26
(
new
GeoLib
::
Polyline
(
points
));
ply_26
->
addPoint
(
2
);
ply_26
->
addPoint
(
6
);
plys
->
push_back
(
ply_26
);
GeoLib
::
Polyline
*
ply_37
(
new
GeoLib
::
Polyline
(
points
));
ply_37
->
addPoint
(
3
);
ply_37
->
addPoint
(
7
);
plys
->
push_back
(
ply_37
);
geometries
.
addPolylineVec
(
std
::
move
(
plys
),
cell_names
.
back
(),
nullptr
);
}
}
}
if
(
geometries
.
mergeGeometries
(
cell_names
,
geometry_name
)
==
2
)
geometry_name
=
cell_names
.
front
();
}
#endif // NDEBUG
}
// end namespace MeshLib
This diff is collapsed.
Click to expand it.
MeshLib/MeshSearch/MeshElementGrid.h
0 → 100644
+
120
−
0
View file @
b97dba8a
/*
* \brief Declaration of the MeshElementGrid class.
*
* \copyright
* Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*/
#ifndef MESHELEMENTGRID_H_
#define MESHELEMENTGRID_H_
#include
<array>
#include
<limits>
#include
<vector>
#include
"GeoLib/AABB.h"
#include
"MathLib/Point3d.h"
namespace
GeoLib
{
class
GEOObjects
;
}
namespace
MeshLib
{
// forward declarations
class
Mesh
;
class
Element
;
/// MeshElementGrid implements a grid data structure supporting search
/// operations and covers a given mesh. It consists of grid cells that are all
/// of the same size. Grid cells contain pointers to intersecting mesh elements.
/// @attention The user has to ensure the validity of the pointers while the
/// MeshElementGrid instance lives.
class
MeshElementGrid
final
{
#ifndef NDEBUG
friend
void
getGridGeometry
(
MeshLib
::
MeshElementGrid
const
&
grid
,
GeoLib
::
GEOObjects
&
geometries
,
std
::
string
&
geometry_name
);
#endif
public:
/// Constructs a grid. Grid cells contains intersecting mesh elements.
/// @param mesh the MeshLib::Mesh instance the grid will be constructed from
explicit
MeshElementGrid
(
MeshLib
::
Mesh
const
&
mesh
);
/// Fill and return a vector containing elements of all grid cells that have
/// a non-empty intersection with the box that is defined by min and max.
/// @param min min point of the box
/// @param max max point of the box
/// @return a (possible empty) vector of elements
template
<
typename
POINT
>
std
::
vector
<
MeshLib
::
Element
const
*>
getElementsInVolume
(
POINT
const
&
min
,
POINT
const
&
max
)
const
{
auto
const
min_coords
(
getGridCellCoordinates
(
min
));
auto
const
max_coords
(
getGridCellCoordinates
(
max
));
if
(
!
min_coords
.
first
)
{
WARN
(
"MeshElementGrid::getElementsInVolume: Min point (%f,%f,%f) "
"outside of MeshElementGrid [%f,%f) x [%f,%f) x [%f,%f)."
,
min
[
0
],
min
[
1
],
min
[
2
],
_aabb
.
getMinPoint
()[
0
],
_aabb
.
getMaxPoint
()[
0
],
_aabb
.
getMinPoint
()[
1
],
_aabb
.
getMaxPoint
()[
1
],
_aabb
.
getMinPoint
()[
2
],
_aabb
.
getMaxPoint
()[
2
]);
}
if
(
!
max_coords
.
first
)
{
WARN
(
"MeshElementGrid::getElementsInVolume: Max point (%f,%f,%f) "
"outside of MeshElementGrid [%f,%f) x [%f,%f) x [%f,%f)."
,
max
[
0
],
max
[
1
],
max
[
2
],
_aabb
.
getMinPoint
()[
0
],
_aabb
.
getMaxPoint
()[
0
],
_aabb
.
getMinPoint
()[
1
],
_aabb
.
getMaxPoint
()[
1
],
_aabb
.
getMinPoint
()[
2
],
_aabb
.
getMaxPoint
()[
2
]);
}
std
::
vector
<
MeshLib
::
Element
const
*>
elements_vec
;
const
std
::
size_t
n_plane
(
_n_steps
[
0
]
*
_n_steps
[
1
]);
for
(
std
::
size_t
i
(
min_coords
.
second
[
0
]);
i
<=
max_coords
.
second
[
0
];
i
++
)
{
for
(
std
::
size_t
j
(
min_coords
.
second
[
1
]);
j
<=
max_coords
.
second
[
1
];
j
++
)
{
for
(
std
::
size_t
k
(
min_coords
.
second
[
2
]);
k
<=
max_coords
.
second
[
2
];
k
++
)
{
std
::
size_t
idx
(
i
+
j
*
_n_steps
[
0
]
+
k
*
n_plane
);
std
::
copy
(
_elements_in_grid_box
[
idx
].
begin
(),
_elements_in_grid_box
[
idx
].
end
(),
elements_vec
.
end
());
}
}
}
return
elements_vec
;
}
private
:
void
sortElementsInGridCells
(
MeshLib
::
Mesh
const
&
sfc_mesh
);
bool
sortElementInGridCells
(
MeshLib
::
Element
const
&
element
);
GeoLib
::
AABB
_aabb
;
/// Computes the grid cell coordinates for given point. The first element of
/// the returned pair (bool) is true if the point is within the grid, else
/// false.
std
::
pair
<
bool
,
std
::
array
<
std
::
size_t
,
3
>>
getGridCellCoordinates
(
MathLib
::
Point3d
const
&
p
)
const
;
std
::
array
<
double
,
3
>
_step_sizes
;
std
::
array
<
double
,
3
>
_inverse_step_sizes
;
std
::
array
<
std
::
size_t
,
3
>
_n_steps
;
std
::
vector
<
std
::
vector
<
MeshLib
::
Element
const
*>>
_elements_in_grid_box
;
};
#ifndef NDEBUG
/// Transfers the grid cells to a geometry. The grid-geometry can be viewed
/// using the DataExplorer. The visualization can be used to explain the
/// algorithm or to find bugs in the algorithm.
void
getGridGeometry
(
MeshLib
::
MeshElementGrid
const
&
grid
,
GeoLib
::
GEOObjects
&
geometries
,
std
::
string
&
geometry_name
);
#endif
}
// end namespace MeshLib
#endif
/* MESHELEMENTGRID_H_ */
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment