cc-csf 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cc_csf-1.0.0/MANIFEST.in +4 -0
- cc_csf-1.0.0/PKG-INFO +98 -0
- cc_csf-1.0.0/README.md +83 -0
- cc_csf-1.0.0/cc_csf.cpp +65 -0
- cc_csf-1.0.0/pyproject.toml +32 -0
- cc_csf-1.0.0/setup.cfg +4 -0
- cc_csf-1.0.0/setup.py +32 -0
- cc_csf-1.0.0/src/CSF.cpp +212 -0
- cc_csf-1.0.0/src/CSF.h +133 -0
- cc_csf-1.0.0/src/Cloth.cpp +428 -0
- cc_csf-1.0.0/src/Cloth.h +165 -0
- cc_csf-1.0.0/src/Constraint.cpp +42 -0
- cc_csf-1.0.0/src/Constraint.h +47 -0
- cc_csf-1.0.0/src/Particle.cpp +58 -0
- cc_csf-1.0.0/src/Particle.h +170 -0
- cc_csf-1.0.0/src/Rasterization.cpp +146 -0
- cc_csf-1.0.0/src/Rasterization.h +44 -0
- cc_csf-1.0.0/src/Vec3.h +92 -0
- cc_csf-1.0.0/src/XYZReader.cpp +45 -0
- cc_csf-1.0.0/src/XYZReader.h +31 -0
- cc_csf-1.0.0/src/c2cdist.cpp +61 -0
- cc_csf-1.0.0/src/c2cdist.h +46 -0
- cc_csf-1.0.0/src/cc_csf.egg-info/PKG-INFO +98 -0
- cc_csf-1.0.0/src/cc_csf.egg-info/SOURCES.txt +27 -0
- cc_csf-1.0.0/src/cc_csf.egg-info/dependency_links.txt +1 -0
- cc_csf-1.0.0/src/cc_csf.egg-info/requires.txt +1 -0
- cc_csf-1.0.0/src/cc_csf.egg-info/top_level.txt +1 -0
- cc_csf-1.0.0/src/point_cloud.cpp +40 -0
- cc_csf-1.0.0/src/point_cloud.h +64 -0
cc_csf-1.0.0/MANIFEST.in
ADDED
cc_csf-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cc_csf
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: High-performance Zero-Copy OpenMP Pybind11 Cloth Simulation Filter (CSF)
|
|
5
|
+
Author-email: Aman Ranjan <er.amanranjan@gmail.com>
|
|
6
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
7
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: numpy>=1.20
|
|
15
|
+
|
|
16
|
+
# cc_csf (Zero-Copy OpenMP Cloth Simulation Filter)
|
|
17
|
+
|
|
18
|
+
High-performance Python wrapper for the Cloth Simulation Filter (CSF) algorithm using Pybind11, OpenMP parallelization, and zero-copy NumPy array buffers.
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
### From Pre-built Wheel
|
|
23
|
+
```bash
|
|
24
|
+
uv pip install cc_csf-1.0.0-cp312-cp312-linux_x86_64.whl
|
|
25
|
+
# or
|
|
26
|
+
pip install cc_csf-1.0.0-cp312-cp312-linux_x86_64.whl
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### From Source (In-place or install)
|
|
30
|
+
```bash
|
|
31
|
+
uv pip install -e .
|
|
32
|
+
# or
|
|
33
|
+
pip install .
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick Start Example
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
import numpy as np
|
|
40
|
+
import cc_csf
|
|
41
|
+
|
|
42
|
+
# Initialize filter
|
|
43
|
+
csf = cc_csf.CSF()
|
|
44
|
+
|
|
45
|
+
# Configure parameters:
|
|
46
|
+
# set_params(bSloopSmooth, cloth_resolution, iterations, class_threshold, rigidness)
|
|
47
|
+
csf.set_params(True, 0.5, 500, 0.3, 1)
|
|
48
|
+
|
|
49
|
+
# Pass Nx3 float64 numpy array (zero-copy buffer)
|
|
50
|
+
xyz = np.random.rand(100000, 3) * 50.0
|
|
51
|
+
csf.set_point_cloud(xyz)
|
|
52
|
+
|
|
53
|
+
# Execute OpenMP-accelerated filtering
|
|
54
|
+
# Returns list of integer indices belonging to ground points
|
|
55
|
+
ground_indices = csf.do_filtering()
|
|
56
|
+
print(f"Detected {len(ground_indices)} ground points out of {len(xyz)}")
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
# Building
|
|
60
|
+
|
|
61
|
+
## Operating System Dependencies (Ubuntu / Debian / Linux)
|
|
62
|
+
Ensure a C++14-compliant compiler and OpenMP libraries are installed:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
sudo apt update
|
|
66
|
+
sudo apt install -y build-essential g++ libomp-dev python3-dev
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Python Build Dependencies
|
|
70
|
+
Install build tools in your virtual environment:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Using uv (recommended)
|
|
74
|
+
uv pip install pybind11 wheel build setuptools
|
|
75
|
+
|
|
76
|
+
# Or using standard pip
|
|
77
|
+
pip install pybind11 wheel build setuptools
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Step 1: Compile the Wheel
|
|
81
|
+
From the project root, run:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Using uv with --no-isolation (avoids Debian/Ubuntu ensurepip issues)
|
|
85
|
+
uv run python -m build --no-isolation --wheel cc_csf --outdir wheels
|
|
86
|
+
```
|
|
87
|
+
> [!NOTE]
|
|
88
|
+
> The `--no-isolation` flag uses the current environment's `pybind11` and `setuptools`, bypassing Debian/Ubuntu minimal python `ensurepip` constraints.
|
|
89
|
+
|
|
90
|
+
### Step 2: Verify the Built Wheel
|
|
91
|
+
The compiled binary wheel is stored in `wheels/`:
|
|
92
|
+
```bash
|
|
93
|
+
ls -lh wheels/
|
|
94
|
+
# Output: cc_csf-1.0.0-cp312-cp312-linux_x86_64.whl
|
|
95
|
+
```
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
|
cc_csf-1.0.0/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# cc_csf (Zero-Copy OpenMP Cloth Simulation Filter)
|
|
2
|
+
|
|
3
|
+
High-performance Python wrapper for the Cloth Simulation Filter (CSF) algorithm using Pybind11, OpenMP parallelization, and zero-copy NumPy array buffers.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### From Pre-built Wheel
|
|
8
|
+
```bash
|
|
9
|
+
uv pip install cc_csf-1.0.0-cp312-cp312-linux_x86_64.whl
|
|
10
|
+
# or
|
|
11
|
+
pip install cc_csf-1.0.0-cp312-cp312-linux_x86_64.whl
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### From Source (In-place or install)
|
|
15
|
+
```bash
|
|
16
|
+
uv pip install -e .
|
|
17
|
+
# or
|
|
18
|
+
pip install .
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start Example
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
import numpy as np
|
|
25
|
+
import cc_csf
|
|
26
|
+
|
|
27
|
+
# Initialize filter
|
|
28
|
+
csf = cc_csf.CSF()
|
|
29
|
+
|
|
30
|
+
# Configure parameters:
|
|
31
|
+
# set_params(bSloopSmooth, cloth_resolution, iterations, class_threshold, rigidness)
|
|
32
|
+
csf.set_params(True, 0.5, 500, 0.3, 1)
|
|
33
|
+
|
|
34
|
+
# Pass Nx3 float64 numpy array (zero-copy buffer)
|
|
35
|
+
xyz = np.random.rand(100000, 3) * 50.0
|
|
36
|
+
csf.set_point_cloud(xyz)
|
|
37
|
+
|
|
38
|
+
# Execute OpenMP-accelerated filtering
|
|
39
|
+
# Returns list of integer indices belonging to ground points
|
|
40
|
+
ground_indices = csf.do_filtering()
|
|
41
|
+
print(f"Detected {len(ground_indices)} ground points out of {len(xyz)}")
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
# Building
|
|
45
|
+
|
|
46
|
+
## Operating System Dependencies (Ubuntu / Debian / Linux)
|
|
47
|
+
Ensure a C++14-compliant compiler and OpenMP libraries are installed:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
sudo apt update
|
|
51
|
+
sudo apt install -y build-essential g++ libomp-dev python3-dev
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Python Build Dependencies
|
|
55
|
+
Install build tools in your virtual environment:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Using uv (recommended)
|
|
59
|
+
uv pip install pybind11 wheel build setuptools
|
|
60
|
+
|
|
61
|
+
# Or using standard pip
|
|
62
|
+
pip install pybind11 wheel build setuptools
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Step 1: Compile the Wheel
|
|
66
|
+
From the project root, run:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Using uv with --no-isolation (avoids Debian/Ubuntu ensurepip issues)
|
|
70
|
+
uv run python -m build --no-isolation --wheel cc_csf --outdir wheels
|
|
71
|
+
```
|
|
72
|
+
> [!NOTE]
|
|
73
|
+
> The `--no-isolation` flag uses the current environment's `pybind11` and `setuptools`, bypassing Debian/Ubuntu minimal python `ensurepip` constraints.
|
|
74
|
+
|
|
75
|
+
### Step 2: Verify the Built Wheel
|
|
76
|
+
The compiled binary wheel is stored in `wheels/`:
|
|
77
|
+
```bash
|
|
78
|
+
ls -lh wheels/
|
|
79
|
+
# Output: cc_csf-1.0.0-cp312-cp312-linux_x86_64.whl
|
|
80
|
+
```
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
|
cc_csf-1.0.0/cc_csf.cpp
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#include <pybind11/pybind11.h>
|
|
2
|
+
#include <pybind11/numpy.h>
|
|
3
|
+
#include <pybind11/stl.h>
|
|
4
|
+
#include "CSF.h"
|
|
5
|
+
|
|
6
|
+
namespace py = pybind11;
|
|
7
|
+
|
|
8
|
+
class CSFWrapper {
|
|
9
|
+
public:
|
|
10
|
+
CSF csf;
|
|
11
|
+
|
|
12
|
+
CSFWrapper() {}
|
|
13
|
+
|
|
14
|
+
void set_params(bool bSloopSmooth, double cloth_resolution, int iterations, double class_threshold, int rigidness) {
|
|
15
|
+
csf.params.bSloopSmooth = bSloopSmooth;
|
|
16
|
+
csf.params.cloth_resolution = cloth_resolution;
|
|
17
|
+
csf.params.interations = iterations;
|
|
18
|
+
csf.params.class_threshold = class_threshold;
|
|
19
|
+
csf.params.rigidness = rigidness;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
void set_point_cloud(py::array_t<double> xyz) {
|
|
23
|
+
py::buffer_info buf = xyz.request();
|
|
24
|
+
if (buf.ndim != 2 || buf.shape[1] != 3) {
|
|
25
|
+
throw std::runtime_error("Input array must be Nx3");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
int rows = buf.shape[0];
|
|
29
|
+
double *ptr = static_cast<double *>(buf.ptr);
|
|
30
|
+
|
|
31
|
+
csf.getPointCloud().resize(rows);
|
|
32
|
+
|
|
33
|
+
#ifdef CSF_USE_OPENMP
|
|
34
|
+
#pragma omp parallel for
|
|
35
|
+
#endif
|
|
36
|
+
for (int i = 0; i < rows; i++) {
|
|
37
|
+
double px = ptr[i * 3 + 0];
|
|
38
|
+
double py = ptr[i * 3 + 1];
|
|
39
|
+
double pz = ptr[i * 3 + 2];
|
|
40
|
+
|
|
41
|
+
csf::Point p;
|
|
42
|
+
p.x = px;
|
|
43
|
+
p.y = -pz;
|
|
44
|
+
p.z = py;
|
|
45
|
+
|
|
46
|
+
csf.getPointCloud()[i] = p;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
std::vector<int> do_filtering() {
|
|
51
|
+
std::vector<int> ground_indexes, off_ground_indexes;
|
|
52
|
+
csf.do_filtering(ground_indexes, off_ground_indexes);
|
|
53
|
+
return ground_indexes;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
PYBIND11_MODULE(cc_csf, m) {
|
|
58
|
+
m.doc() = "Zero-copy Pybind11 wrapper for CloudCompare CSF";
|
|
59
|
+
|
|
60
|
+
py::class_<CSFWrapper>(m, "CSF")
|
|
61
|
+
.def(py::init<>())
|
|
62
|
+
.def("set_params", &CSFWrapper::set_params)
|
|
63
|
+
.def("set_point_cloud", &CSFWrapper::set_point_cloud)
|
|
64
|
+
.def("do_filtering", &CSFWrapper::do_filtering);
|
|
65
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "pybind11>=2.10", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "cc_csf"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "High-performance Zero-Copy OpenMP Pybind11 Cloth Simulation Filter (CSF)"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
authors = [
|
|
12
|
+
{ name = "Aman Ranjan", email = "er.amanranjan@gmail.com" }
|
|
13
|
+
]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3.10",
|
|
16
|
+
"Programming Language :: Python :: 3.11",
|
|
17
|
+
"Programming Language :: Python :: 3.12",
|
|
18
|
+
"Programming Language :: Python :: 3.13",
|
|
19
|
+
"Development Status :: 5 - Production/Stable",
|
|
20
|
+
"Topic :: Scientific/Engineering :: GIS",
|
|
21
|
+
]
|
|
22
|
+
dependencies = [
|
|
23
|
+
"numpy>=1.20",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[tool.cibuildwheel]
|
|
27
|
+
build = "cp310-* cp311-* cp312-* cp313-*"
|
|
28
|
+
skip = "pp* *i686* *musllinux* *aarch64*"
|
|
29
|
+
|
|
30
|
+
[tool.cibuildwheel.linux]
|
|
31
|
+
manylinux-x86_64-image = "manylinux_2_28"
|
|
32
|
+
repair-wheel-command = "auditwheel repair -w {dest_dir} {wheel}"
|
cc_csf-1.0.0/setup.cfg
ADDED
cc_csf-1.0.0/setup.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from setuptools import setup, Extension
|
|
2
|
+
import pybind11
|
|
3
|
+
|
|
4
|
+
sources = [
|
|
5
|
+
"cc_csf.cpp",
|
|
6
|
+
"src/c2cdist.cpp",
|
|
7
|
+
"src/Cloth.cpp",
|
|
8
|
+
"src/Constraint.cpp",
|
|
9
|
+
"src/CSF.cpp",
|
|
10
|
+
"src/Particle.cpp",
|
|
11
|
+
"src/point_cloud.cpp",
|
|
12
|
+
"src/Rasterization.cpp",
|
|
13
|
+
"src/XYZReader.cpp",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
ext_modules = [
|
|
17
|
+
Extension(
|
|
18
|
+
"cc_csf",
|
|
19
|
+
sources=sources,
|
|
20
|
+
include_dirs=[pybind11.get_include(), "src"],
|
|
21
|
+
extra_compile_args=["-O3", "-march=native", "-ffast-math", "-fopenmp", "-std=c++14"],
|
|
22
|
+
extra_link_args=["-fopenmp"],
|
|
23
|
+
define_macros=[("CSF_USE_OPENMP", "1")],
|
|
24
|
+
),
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
setup(
|
|
28
|
+
name="cc_csf",
|
|
29
|
+
version="1.0.0",
|
|
30
|
+
description="High-performance Zero-Copy OpenMP Pybind11 Cloth Simulation Filter (CSF)",
|
|
31
|
+
ext_modules=ext_modules,
|
|
32
|
+
)
|
cc_csf-1.0.0/src/CSF.cpp
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
// ======================================================================================
|
|
2
|
+
// Copyright 2017 State Key Laboratory of Remote Sensing Science,
|
|
3
|
+
// Institute of Remote Sensing Science and Engineering, Beijing Normal University
|
|
4
|
+
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
// ======================================================================================
|
|
17
|
+
|
|
18
|
+
#define DLL_IMPLEMENT
|
|
19
|
+
|
|
20
|
+
#include "CSF.h"
|
|
21
|
+
#include "XYZReader.h"
|
|
22
|
+
#include "Vec3.h"
|
|
23
|
+
#include "Rasterization.h"
|
|
24
|
+
#include "c2cdist.h"
|
|
25
|
+
#include <fstream>
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
CSF::CSF(int index) {
|
|
29
|
+
params.bSloopSmooth = true;
|
|
30
|
+
params.time_step = 0.65;
|
|
31
|
+
params.class_threshold = 0.5;
|
|
32
|
+
params.cloth_resolution = 1;
|
|
33
|
+
params.rigidness = 3;
|
|
34
|
+
params.interations = 500;
|
|
35
|
+
|
|
36
|
+
this->index = index;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
CSF::CSF() {
|
|
40
|
+
params.bSloopSmooth = true;
|
|
41
|
+
params.time_step = 0.65;
|
|
42
|
+
params.class_threshold = 0.5;
|
|
43
|
+
params.cloth_resolution = 1;
|
|
44
|
+
params.rigidness = 3;
|
|
45
|
+
params.interations = 500;
|
|
46
|
+
this->index = 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
CSF::~CSF()
|
|
50
|
+
{}
|
|
51
|
+
|
|
52
|
+
void CSF::setPointCloud(std::vector<csf::Point> points) {
|
|
53
|
+
point_cloud.resize(points.size());
|
|
54
|
+
|
|
55
|
+
int pointCount = static_cast<int>(points.size());
|
|
56
|
+
#ifdef CSF_USE_OPENMP
|
|
57
|
+
#pragma omp parallel for
|
|
58
|
+
#endif
|
|
59
|
+
for (int i = 0; i < pointCount; i++) {
|
|
60
|
+
csf::Point las;
|
|
61
|
+
las.x = points[i].x;
|
|
62
|
+
las.y = -points[i].z;
|
|
63
|
+
las.z = points[i].y;
|
|
64
|
+
point_cloud[i] = las;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
void CSF::setPointCloud(double *points, int rows, int cols) {
|
|
69
|
+
point_cloud.resize(rows);
|
|
70
|
+
#define A(i, j) points[i * cols + j]
|
|
71
|
+
for (int i = 0; i < rows; i++) {
|
|
72
|
+
point_cloud[i] = {A(i, 0), -A(i, 2) , A(i, 1)};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
void CSF::setPointCloud(double *points, int rows) {
|
|
79
|
+
#define Mat(i, j) points[i + j * rows]
|
|
80
|
+
point_cloud.resize(rows);
|
|
81
|
+
for (int i = 0; i < rows; i++) {
|
|
82
|
+
point_cloud[i] = {Mat(i, 0), -Mat(i, 2) , Mat(i, 1)};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
void CSF::setPointCloud(csf::PointCloud& pc) {
|
|
87
|
+
point_cloud.resize(pc.size());
|
|
88
|
+
int pointCount = static_cast<int>(pc.size());
|
|
89
|
+
#ifdef CSF_USE_OPENMP
|
|
90
|
+
#pragma omp parallel for
|
|
91
|
+
#endif
|
|
92
|
+
for (int i = 0; i < pointCount; i++) {
|
|
93
|
+
csf::Point las;
|
|
94
|
+
las.x = pc[i].x;
|
|
95
|
+
las.y = -pc[i].z;
|
|
96
|
+
las.z = pc[i].y;
|
|
97
|
+
point_cloud[i] = las;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
void CSF::readPointsFromFile(std::string filename) {
|
|
103
|
+
this->point_cloud.resize(0);
|
|
104
|
+
read_xyz(filename, this->point_cloud);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
Cloth CSF::do_cloth() {
|
|
109
|
+
// Terrain
|
|
110
|
+
std::cout << "[" << this->index << "] Configuring terrain..." << std::endl;
|
|
111
|
+
csf::Point bbMin, bbMax;
|
|
112
|
+
point_cloud.computeBoundingBox(bbMin, bbMax);
|
|
113
|
+
std::cout << "[" << this->index << "] - bbMin: " << bbMin.x << " " << bbMin.y << " " << bbMin.z << std::endl;
|
|
114
|
+
std::cout << "[" << this->index << "] - bbMax: " << bbMax.x << " " << bbMax.y << " " << bbMax.z << std::endl;
|
|
115
|
+
|
|
116
|
+
double cloth_y_height = 0.05;
|
|
117
|
+
|
|
118
|
+
int clothbuffer_d = 2;
|
|
119
|
+
Vec3 origin_pos(
|
|
120
|
+
bbMin.x - clothbuffer_d *params.cloth_resolution,
|
|
121
|
+
bbMax.y + cloth_y_height,
|
|
122
|
+
bbMin.z - clothbuffer_d *params.cloth_resolution
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
int width_num = static_cast<int>(
|
|
126
|
+
std::floor((bbMax.x - bbMin.x) / params.cloth_resolution)
|
|
127
|
+
) + 2 * clothbuffer_d;
|
|
128
|
+
|
|
129
|
+
int height_num = static_cast<int>(
|
|
130
|
+
std::floor((bbMax.z - bbMin.z) / params.cloth_resolution)
|
|
131
|
+
) + 2 * clothbuffer_d;
|
|
132
|
+
|
|
133
|
+
std::cout << "[" << this->index << "] Configuring cloth..." << std::endl;
|
|
134
|
+
std::cout << "[" << this->index << "] - width: " << width_num << " "
|
|
135
|
+
<< "height: " << height_num << std::endl;
|
|
136
|
+
|
|
137
|
+
Cloth cloth(
|
|
138
|
+
origin_pos,
|
|
139
|
+
width_num,
|
|
140
|
+
height_num,
|
|
141
|
+
params.cloth_resolution,
|
|
142
|
+
params.cloth_resolution,
|
|
143
|
+
0.3,
|
|
144
|
+
9999,
|
|
145
|
+
params.rigidness,
|
|
146
|
+
params.time_step
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
std::cout << "[" << this->index << "] Rasterizing..." << std::endl;
|
|
150
|
+
Rasterization::RasterTerrian(cloth, point_cloud, cloth.getHeightvals());
|
|
151
|
+
|
|
152
|
+
double time_step2 = params.time_step * params.time_step;
|
|
153
|
+
double gravity = 0.2;
|
|
154
|
+
|
|
155
|
+
std::cout << "[" << this->index << "] Simulating..." << std::endl;
|
|
156
|
+
cloth.addForce(Vec3(0, -gravity, 0) * time_step2);
|
|
157
|
+
|
|
158
|
+
// boost::progress_display pd(params.interations);
|
|
159
|
+
for (int i = 0; i < params.interations; i++) {
|
|
160
|
+
double maxDiff = cloth.timeStep();
|
|
161
|
+
cloth.terrCollision();
|
|
162
|
+
//params.class_threshold / 100
|
|
163
|
+
if ((maxDiff != 0) && (maxDiff < 0.005)) {
|
|
164
|
+
// early stop
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
// pd++;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (params.bSloopSmooth) {
|
|
171
|
+
std::cout << "[" << this->index << "] - post handle..." << std::endl;
|
|
172
|
+
cloth.movableFilter();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return cloth;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
std::vector<double> CSF::do_cloth_export() {
|
|
179
|
+
auto cloth = do_cloth();
|
|
180
|
+
return cloth.toVector();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
void CSF::do_filtering(std::vector<int>& groundIndexes,
|
|
184
|
+
std::vector<int>& offGroundIndexes,
|
|
185
|
+
bool exportCloth) {
|
|
186
|
+
auto cloth = do_cloth();
|
|
187
|
+
if (exportCloth)
|
|
188
|
+
cloth.saveToFile();
|
|
189
|
+
c2cdist c2c(params.class_threshold);
|
|
190
|
+
c2c.calCloud2CloudDist(cloth, point_cloud, groundIndexes, offGroundIndexes);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
void CSF::savePoints(std::vector<int> grp, std::string path) {
|
|
195
|
+
if (path == "") {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
std::ofstream f1(path.c_str(), std::ios::out);
|
|
200
|
+
|
|
201
|
+
if (!f1)
|
|
202
|
+
return;
|
|
203
|
+
|
|
204
|
+
for (std::size_t i = 0; i < grp.size(); i++) {
|
|
205
|
+
f1 << std::fixed << std::setprecision(8)
|
|
206
|
+
<< point_cloud[grp[i]].x << " "
|
|
207
|
+
<< point_cloud[grp[i]].z << " "
|
|
208
|
+
<< -point_cloud[grp[i]].y << std::endl;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
f1.close();
|
|
212
|
+
}
|
cc_csf-1.0.0/src/CSF.h
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// ======================================================================================
|
|
2
|
+
// Copyright 2017 State Key Laboratory of Remote Sensing Science,
|
|
3
|
+
// Institute of Remote Sensing Science and Engineering, Beijing Normal University
|
|
4
|
+
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
// ======================================================================================
|
|
17
|
+
|
|
18
|
+
// #######################################################################################
|
|
19
|
+
// # #
|
|
20
|
+
// # CSF: Airborne LiDAR filtering based on Cloth Simulation #
|
|
21
|
+
// # #
|
|
22
|
+
// # Please cite the following paper, If you use this software in your work. #
|
|
23
|
+
// # #
|
|
24
|
+
// # Zhang W, Qi J, Wan P, Wang H, Xie D, Wang X, Yan G. An Easy-to-Use Airborne LiDAR #
|
|
25
|
+
// # Data Filtering Method Based on Cloth Simulation. Remote Sensing. 2016; 8(6):501. #
|
|
26
|
+
// # (http://ramm.bnu.edu.cn/) #
|
|
27
|
+
// # #
|
|
28
|
+
// # Wuming Zhang; Jianbo Qi; Peng Wan; Hongtao Wang #
|
|
29
|
+
// # #
|
|
30
|
+
// # contact us: 2009zwm@gmail.com; wpqjbzwm@126.com #
|
|
31
|
+
// # #
|
|
32
|
+
// #######################################################################################
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
// cloth simulation filter for airborne lidar filtering
|
|
36
|
+
#ifndef _CSF_H_
|
|
37
|
+
#define _CSF_H_
|
|
38
|
+
#include <vector>
|
|
39
|
+
#include <string>
|
|
40
|
+
#include "point_cloud.h"
|
|
41
|
+
#include "Cloth.h"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
struct Params {
|
|
45
|
+
// refer to the website:http://ramm.bnu.edu.cn/projects/CSF/ for the setting of these paramters
|
|
46
|
+
bool bSloopSmooth;
|
|
47
|
+
double time_step;
|
|
48
|
+
double class_threshold;
|
|
49
|
+
double cloth_resolution;
|
|
50
|
+
int rigidness;
|
|
51
|
+
int interations;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
#ifdef _CSF_DLL_EXPORT_
|
|
55
|
+
# ifdef DLL_IMPLEMENT
|
|
56
|
+
# define DLL_API __declspec(dllexport)
|
|
57
|
+
# else // ifdef DLL_IMPLEMENT
|
|
58
|
+
# define DLL_API __declspec(dllimport)
|
|
59
|
+
# endif // ifdef DLL_IMPLEMENT
|
|
60
|
+
#endif // ifdef _CSF_DLL_EXPORT_
|
|
61
|
+
|
|
62
|
+
#ifdef _CSF_DLL_EXPORT_
|
|
63
|
+
class DLL_API CSF
|
|
64
|
+
#else // ifdef _CSF_DLL_EXPORT_
|
|
65
|
+
class CSF
|
|
66
|
+
#endif // ifdef _CSF_DLL_EXPORT_
|
|
67
|
+
{
|
|
68
|
+
public:
|
|
69
|
+
|
|
70
|
+
CSF(int index);
|
|
71
|
+
CSF();
|
|
72
|
+
~CSF();
|
|
73
|
+
|
|
74
|
+
// set pointcloud from vector
|
|
75
|
+
void setPointCloud(std::vector<csf::Point> points);
|
|
76
|
+
|
|
77
|
+
// set point cloud from a two-dimentional array. it defines a N*3 point cloud by the given rows.
|
|
78
|
+
// it is the method used to set point cloud from python (numpy array)
|
|
79
|
+
void setPointCloud(double *points, int rows, int cols);
|
|
80
|
+
|
|
81
|
+
// set point cloud from a one-dimentional array. it defines a N*3 point cloud by the given rows.
|
|
82
|
+
// it is the method used to set point cloud from matlab
|
|
83
|
+
void setPointCloud(double *points, int rows);
|
|
84
|
+
|
|
85
|
+
// read pointcloud from txt file: (X Y Z) for each line
|
|
86
|
+
void readPointsFromFile(std::string filename);
|
|
87
|
+
|
|
88
|
+
inline csf::PointCloud& getPointCloud() {
|
|
89
|
+
return point_cloud;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
inline const csf::PointCloud& getPointCloud() const {
|
|
93
|
+
return point_cloud;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// save points to file
|
|
97
|
+
void savePoints(std::vector<int> grp, std::string path);
|
|
98
|
+
|
|
99
|
+
// get size of pointcloud
|
|
100
|
+
std::size_t size() {
|
|
101
|
+
return point_cloud.size();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// PointCloud set pointcloud
|
|
105
|
+
void setPointCloud(csf::PointCloud& pc);
|
|
106
|
+
|
|
107
|
+
// The results are index of ground points in the original
|
|
108
|
+
// pointcloud and write the cloth particles coordinates
|
|
109
|
+
void do_filtering(std::vector<int>& groundIndexes,
|
|
110
|
+
std::vector<int>& offGroundIndexes,
|
|
111
|
+
bool exportCloth=true);
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
std::vector<double> do_cloth_export();
|
|
115
|
+
|
|
116
|
+
private:
|
|
117
|
+
|
|
118
|
+
// Do the filtering and return the Cloth object
|
|
119
|
+
Cloth do_cloth();
|
|
120
|
+
|
|
121
|
+
#ifdef _CSF_DLL_EXPORT_
|
|
122
|
+
class __declspec (dllexport)csf::PointCloud point_cloud;
|
|
123
|
+
#else // ifdef _CSF_DLL_EXPORT_
|
|
124
|
+
csf::PointCloud point_cloud;
|
|
125
|
+
#endif // ifdef _CSF_DLL_EXPORT_
|
|
126
|
+
|
|
127
|
+
public:
|
|
128
|
+
|
|
129
|
+
Params params;
|
|
130
|
+
int index;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
#endif // ifndef _CSF_H_
|