Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update grid decimation #4

Merged
merged 4 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 21 additions & 14 deletions src/filter_grid_decimation/GridDecimationFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,22 @@ void GridDecimationFilter::processOne(BOX2D bounds, PointRef& point, PointViewPt
double x = point.getFieldAs<double>(Dimension::Id::X);
double y = point.getFieldAs<double>(Dimension::Id::Y);
int id = point.getFieldAs<double>(Dimension::Id::PointId);

double d_width_pt = std::ceil((x - bounds.minx) / m_args->m_edgeLength);
double d_height_pt = std::ceil((y - bounds.miny) / m_args->m_edgeLength);

int width = static_cast<int>(d_width_pt);
int height = static_cast<int>(d_height_pt);

auto ptRefid = this->grid[ std::make_pair(width,height) ];


// if x==(xmax of the cell), we assume the point are in the upper cell
// if y==(ymax of the cell), we assume the point are in the right cell
int width = static_cast<int>((x - bounds.minx) / m_args->m_edgeLength);
int height = static_cast<int>((y - bounds.miny) / m_args->m_edgeLength);

// to avoid numeric pb with the division (append if the point is on the grid)
if (x < bounds.minx+width*m_args->m_edgeLength) width--;
if (y < bounds.miny+height*m_args->m_edgeLength) height--;
if (x >= bounds.minx+(width+1)*m_args->m_edgeLength) width++;
if (y >= bounds.miny+(height+1)*m_args->m_edgeLength) height++;

auto mptRefid = this->grid.find( std::make_pair(width,height) );
assert( mptRefid != this->grid.end() );
auto ptRefid = mptRefid->second;

if (ptRefid==-1)
{
this->grid[ std::make_pair(width,height) ] = point.pointId();
Expand All @@ -107,9 +114,9 @@ void GridDecimationFilter::processOne(BOX2D bounds, PointRef& point, PointViewPt

void GridDecimationFilter::createGrid(BOX2D bounds)
{
double d_width = std::ceil((bounds.maxx - bounds.minx) / m_args->m_edgeLength);
double d_height = std::ceil((bounds.maxy - bounds.miny) / m_args->m_edgeLength);
size_t d_width = std::floor((bounds.maxx - bounds.minx) / m_args->m_edgeLength) + 1;
size_t d_height = std::floor((bounds.maxy - bounds.miny) / m_args->m_edgeLength) + 1;

if (d_width < 0.0 || d_width > (std::numeric_limits<int>::max)())
throwError("Grid width out of range.");
if (d_height < 0.0 || d_height > (std::numeric_limits<int>::max)())
Expand All @@ -123,7 +130,7 @@ void GridDecimationFilter::createGrid(BOX2D bounds)
for (size_t l(0); l<height; l++)
for (size_t c(0); c<width; c++)
{
BOX2D bounds_dalle ( bounds.minx + c*m_args->m_edgeLength, bounds.miny + l*m_args->m_edgeLength,
BOX2D bounds_dalle (bounds.minx + c*m_args->m_edgeLength, bounds.miny + l*m_args->m_edgeLength,
bounds.minx + (c+1)*m_args->m_edgeLength, bounds.miny + (l+1)*m_args->m_edgeLength );
vgrid.push_back(Polygon(bounds_dalle));
this->grid.insert( std::make_pair( std::make_pair(c,l), -1) );
Expand All @@ -143,7 +150,7 @@ PointViewSet GridDecimationFilter::run(PointViewPtr view)
BOX2D bounds;
view->calculateBounds(bounds);
createGrid(bounds);

for (PointId i = 0; i < view->size(); ++i)
{
PointRef point = view->point(i);
Expand Down
Binary file modified test/data/4_6.las
100755 → 100644
Binary file not shown.
79 changes: 57 additions & 22 deletions test/test_grid_decimation.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@

import pdal
import pdaltools.las_info as li
import pytest


def run_filter(type):
def contains(bounds, x, y):
# to be coherent with the grid decimation algorithm
return bounds[0] <= x and x < bounds[1] and bounds[2] <= y and y < bounds[3]


def run_filter(type, resolution):

ini_las = "test/data/4_6.las"
resolution = 10

tmp_out_las = tempfile.NamedTemporaryFile(suffix=".las").name
tmp_out_wkt = tempfile.NamedTemporaryFile(suffix=".wkt").name
tmp_out_wkt = tempfile.NamedTemporaryFile(suffix=f"_{resolution}.wkt").name

filter = "filters.grid_decimation_deprecated"
utils.pdal_has_plugin(filter)
Expand All @@ -34,12 +38,6 @@ def run_filter(type):
"output_dimension": "grid",
"output_wkt": tmp_out_wkt,
},
{
"type": "writers.las",
"extra_dims": "all",
"filename": tmp_out_las,
"where": "grid==1",
},
]

pipeline = pdal.Pipeline(json.dumps(PIPELINE))
Expand All @@ -54,26 +52,63 @@ def run_filter(type):
if pt["grid"] > 0:
nb_pts_grid += 1

# fix dans une autre branche en cours
# assert nb_pts_grid == 3231
assert nb_pts_grid <= nb_dalle
assert nb_pts_grid == nb_dalle

for lig in range(d_height):
for col in range(d_width):

cell = [
bounds[0][0] + col * resolution,
bounds[0][0] + (col + 1) * resolution,
bounds[1][0] + lig * resolution,
bounds[1][0] + (lig + 1) * resolution,
]

nbThreadPtsCrop = 0
ZRef = 0
ZRefGrid = 0

for pt in array:
x = pt["X"]
y = pt["Y"]
if not contains(cell, x, y):
continue

z = pt["Z"]
if type == "max":
if ZRef == 0 or z > ZRef:
ZRef = z
elif type == "min":
if ZRef == 0 or z < ZRef:
ZRef = z

if pt["grid"] > 0:
nbThreadPtsCrop += 1
ZRefGrid = z

assert nbThreadPtsCrop == 1
assert ZRef == ZRefGrid

data = []
with open(tmp_out_wkt, "r") as f:
reader = csv.reader(f, delimiter="\t")
for i, line in enumerate(reader):
data.append(line[0])

# fix dans une autre branche en cours
# assert len(data) == nb_dalle

return nb_pts_grid
assert len(data) == nb_dalle


def test_grid_decimation_max():
run_filter("max")
@pytest.mark.parametrize(
"resolution",
[(10.1), (10.0), (9.8)],
)
def test_grid_decimation_max(resolution):
run_filter("max", resolution)


# fix dans une autre branche en cours
# def test_grid_decimation_min():
# run_filter("min")
@pytest.mark.parametrize(
"resolution",
[(10.3), (10.0), (9.9)],
)
def test_grid_decimation_min(resolution):
run_filter("min", resolution)
Loading