Skip to content

Commit

Permalink
Merge branch 'fwilliams:master' into obj_load_fix
Browse files Browse the repository at this point in the history
  • Loading branch information
NarinderS authored Sep 15, 2024
2 parents 0198deb + 9ee4538 commit 3d7c8c4
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 24 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/build-wheels-and-publish-to-pipy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-20.04, windows-2019, macos-latest]
os: [ubuntu-20.04, windows-2019, macos-13, macos-14]

steps:
- uses: actions/checkout@v3

- name: Set up QEMU
if: runner.os == 'Linux'
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
with:
platforms: all

Expand All @@ -34,9 +34,9 @@ jobs:
CIBW_SKIP: "*-win32 *-manylinux_i686 pp* *-musllinux*"
CIBW_BEFORE_BUILD_LINUX: yum -y install gcc-gfortran lapack-devel blas-devel
CIBW_ARCHS_LINUX: "auto"
CIBW_ARCHS_MACOS: "x86_64 universal2 arm64"
uses: pypa/[email protected]

CIBW_REPAIR_WHEEL_COMMAND_MACOS: "" # delocate-listdeps --all {wheel} && delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}
# CIBW_ARCHS_MACOS: "x86_64 universal2 arm64"
uses: pypa/[email protected]
- uses: actions/upload-artifact@v3
with:
path: ./wheelhouse/*.whl
Expand All @@ -62,7 +62,7 @@ jobs:
# alternatively, to publish when a GitHub Release is created, use the following rule:
# if: github.event_name == 'release' && github.event.action == 'published'
steps:
- uses: actions/download-artifact@v2
- uses: actions/download-artifact@v4.1.7
with:
name: artifact
path: dist
Expand Down
3 changes: 1 addition & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ set(CMAKE_BUILD_TYPE "Release")


option(GEOGRAM_WITH_HLBFGS "Non-linear solver (Yang Liu's HLBFGS)" ON)
#option(NPE_WITH_EIGEN "Whether to use the bundled version of Eigen" ON)
# option(NPE_WITH_EIGEN "Whether to use the bundled version of Eigen" ON)
option(EIGEN_WITH_MKL "Whether to build Eigen with intel MKL or not" OFF)


if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "(arm64)|(ARM64)")
set(NOT_USING_ARM OFF)
else()
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/sections/shape_metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Point Cloud Utils has functions to compute a number of commonly used metrics bet
## Chamfer Distance
The Chamfer distance between two point clouds $P_1 = \{x_i \in \mathbb{R}^3\}_{i=1}^n$ and $P_2 = \{x_j \in \mathbb{R}^3\}_{j=1}^m$ is defined as the average distance between pairs of nearest neighbors between $P_1$ and $P_2$ *i.e.*
$$
\text{chamfer}(P_1, P_2) = \frac{1}{2n} \sum_{x \in P_1} \|x - \text{NN}(x, P_2)\| + \frac{1}{2m} \sum_{x \in P_2} \|x - \text{NN}(x, P_1)\|
\text{chamfer}(P_1, P_2) = \frac{1}{2n} \sum_{x \in P_1}^{n} \|x - \text{NN}(x, P_2)\| + \frac{1}{2m} \sum_{x \in P_2}^{m} \|x - \text{NN}(x, P_1)\|
$$
and $\text{NN}(x, P) = \text{argmin}_{x' \in P} \|x - x'\|$ is the nearest neighbor function.

Expand Down
20 changes: 13 additions & 7 deletions point_cloud_utils/_mesh_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,11 @@ def save(self, filename, dtype=np.float32):
# Handle RBG colors by just concatenating alpha=1
vcolors = self.vertex_data.colors
if vcolors.shape[-1] == 3 and len(vcolors.shape) == 2:
vcolors = np.concatenate([np.ascontiguousarray(self.vertex_data.colors),
np.ones([vcolors.shape[0], 1], dtype=vcolors.dtype)], axis=-1)
if vcolors.dtype == np.uint8 or vcolors.dtype == np.int8:
alphas = np.full([vcolors.shape[0], 1], 255, dtype=vcolors.dtype)
else:
alphas = np.ones([vcolors.shape[0], 1], dtype=vcolors.dtype)
vcolors = np.concatenate([np.ascontiguousarray(self.vertex_data.colors), alphas], axis=-1)

fcolors = self.face_data.colors
if fcolors.shape[-1] == 3 and len(fcolors.shape) == 2:
Expand All @@ -263,8 +266,11 @@ def save(self, filename, dtype=np.float32):

wcolors = self.face_data.wedge_colors
if wcolors.shape[-1] == 3 and len(wcolors.shape) == 3:
wcolors = np.concatenate([np.ascontiguousarray(wcolors),
np.ones([wcolors.shape[0], wcolors.shape[1], 1], dtype=wcolors.dtype)], axis=-1)
if wcolors.dtype == np.uint8 or wcolors.dtype == np.int8:
alphas = np.full([wcolors.shape[0], wcolors.shape[1], 1], 255, dtype=wcolors.dtype)
else:
alphas = np.ones([wcolors.shape[0], wcolors.shape[1], 1], dtype=wcolors.dtype)
wcolors = np.concatenate([np.ascontiguousarray(wcolors), alphas], axis=-1)

if fcolors.shape[0] > 0:
if fcolors.dtype == np.uint8:
Expand All @@ -286,19 +292,19 @@ def save(self, filename, dtype=np.float32):
np.ascontiguousarray(self.vertex_data.positions.astype(dtype)),
np.ascontiguousarray(self.vertex_data.normals.astype(dtype)),
np.ascontiguousarray(self.vertex_data.texcoords.astype(dtype)),
np.ascontiguousarray(vcolors.astype(dtype)),
np.ascontiguousarray((vcolors * 255.0).astype(np.uint8)),
np.ascontiguousarray(self.vertex_data.quality.astype(dtype)),
np.ascontiguousarray(self.vertex_data.radius.astype(dtype)),
np.ascontiguousarray(self.vertex_data.tex_ids.astype(np.int32)),
np.ascontiguousarray(self.vertex_data.flags.astype(np.int32)),

np.ascontiguousarray(self.face_data.vertex_ids.astype(np.int32)),
np.ascontiguousarray(self.face_data.normals.astype(dtype)),
np.ascontiguousarray(fcolors.astype(dtype)),
np.ascontiguousarray((fcolors * 255.0).astype(np.uint8)),
np.ascontiguousarray(self.face_data.quality.astype(dtype)),
np.ascontiguousarray(self.face_data.flags.astype(np.int32)),

np.ascontiguousarray(wcolors.astype(dtype)),
np.ascontiguousarray((wcolors * 255.0).astype(np.uint8)),
np.ascontiguousarray(self.face_data.wedge_normals.astype(dtype)),
np.ascontiguousarray(self.face_data.wedge_texcoords.astype(dtype)),
np.ascontiguousarray(self.face_data.wedge_tex_ids.astype(np.int32)),
Expand Down
5 changes: 4 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ def build_extension(self, ext):
env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(env.get('CXXFLAGS', ''), self.distribution.get_version())
if not os.path.exists(self.build_temp):
os.makedirs(self.build_temp)

if platform.processor() == 'arm':
cmake_args += ['-DCMAKE_OSX_ARCHITECTURES:STRING=arm64']
subprocess.check_call(['cmake'] + cmake_args + [ext.sourcedir], cwd=self.build_temp, env=env)
subprocess.check_call(['cmake', '--build', '.'] + build_args, cwd=self.build_temp)
print() # Add an empty line for cleaner output
Expand All @@ -88,7 +91,7 @@ def main():

setuptools.setup(
name="point-cloud-utils",
version="0.30.4",
version="0.31.0",
author="Francis Williams",
author_email="[email protected]",
description="A Python library for common tasks on 3D point clouds and meshes",
Expand Down
8 changes: 4 additions & 4 deletions src/common/ply_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -373,15 +373,15 @@ void save_mesh_ply(std::string filename,
bool has_v_positions = assert_shape_and_dtype(v_positions, "v_positions", dtype_f, {-num_vertices, 3});
bool has_v_normals = assert_shape_and_dtype(v_normals, "v_normals", dtype_f, {-num_vertices, 3});
bool has_v_texcoords = assert_shape_and_dtype(v_texcoords, "v_texcoords", dtype_f, {-num_vertices, 2});
bool has_v_colors = assert_shape_and_dtype(v_colors, "v_colors", dtype_f, {-num_vertices, 4});
bool has_v_colors = assert_shape_and_dtype(v_colors, "v_colors", pybind11::dtype::of<std::uint8_t>(), {-num_vertices, 4});
bool has_v_quality = assert_shape_and_dtype(v_quality, "v_quality", dtype_f, {-num_vertices});
bool has_v_radius = assert_shape_and_dtype(v_radius, "v_radius", dtype_f, {-num_vertices});
bool has_v_texids = assert_shape_and_dtype(v_texids, "v_texids", dtype_i, {-num_vertices});
bool has_v_flags = assert_shape_and_dtype(v_flags, "v_flags", dtype_i, {-num_vertices});

bool has_f_vertex_ids = assert_shape_and_dtype(f_vertex_ids, "f_vertex_ids", dtype_i, {-num_faces, 3});
bool has_f_normals = assert_shape_and_dtype(f_normals, "f_normals", dtype_f, {-num_faces, 3});
bool has_f_colors = assert_shape_and_dtype(f_colors, "f_colors", dtype_f, {-num_faces, 4});
bool has_f_colors = assert_shape_and_dtype(f_colors, "f_colors", pybind11::dtype::of<std::uint8_t>(), {-num_faces, 4});
bool has_f_quality = assert_shape_and_dtype(f_quality, "f_quality", dtype_f, {-num_faces});
bool has_f_flags = assert_shape_and_dtype(f_flags, "f_flags", dtype_i, {-num_faces});

Expand Down Expand Up @@ -417,7 +417,7 @@ void save_mesh_ply(std::string filename,
}
if (has_v_colors) {
plyf.add_properties_to_element(
"vertex", { "red", "green", "blue", "alpha" }, ply_type_f, num_vertices,
"vertex", { "red", "green", "blue", "alpha" }, tinyply::Type::UINT8, num_vertices,
reinterpret_cast<std::uint8_t*>(v_colors.mutable_data()), tinyply::Type::INVALID, 0);
}
if (has_v_quality) {
Expand Down Expand Up @@ -485,7 +485,7 @@ void save_mesh_ply(std::string filename,
}
if (has_f_colors) {
plyf.add_properties_to_element(
"face", { "red", "green", "blue", "alpha" }, ply_type_f, num_faces,
"face", { "red", "green", "blue", "alpha" }, tinyply::Type::UINT8, num_faces,
reinterpret_cast<std::uint8_t*>(f_colors.mutable_data()), tinyply::Type::INVALID, 0);
}
if (has_f_quality) {
Expand Down
89 changes: 86 additions & 3 deletions src/remove_duplicates.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,92 @@
#include <npe.h>

#include <igl/remove_duplicate_vertices.h>
#include <igl/round.h>
#include <igl/unique_rows.h>
#include <igl/colon.h>

#include "common/common.h"

namespace {

template <
typename DerivedV,
typename DerivedSV,
typename DerivedSVI,
typename DerivedSVJ>
inline void remove_duplicate_vertices(
const Eigen::MatrixBase<DerivedV>& V,
const double epsilon,
Eigen::PlainObjectBase<DerivedSV>& SV,
Eigen::PlainObjectBase<DerivedSVI>& SVI,
Eigen::PlainObjectBase<DerivedSVJ>& SVJ) {

static_assert(
(DerivedSVI::RowsAtCompileTime == 1 || DerivedSVI::ColsAtCompileTime == 1) &&
(DerivedSVJ::RowsAtCompileTime == 1 || DerivedSVJ::ColsAtCompileTime == 1),
"SVI and SVJ need to have RowsAtCompileTime == 1 or ColsAtCompileTime == 1");
if(epsilon > 0) {
DerivedV rV,rSV;
igl::round((V/(epsilon)).eval(),rV);
igl::unique_rows(rV,rSV,SVI,SVJ);
SV = V(SVI.derived(),Eigen::all);
} else {
igl::unique_rows(V,SV,SVI,SVJ);
}
}

template <
typename DerivedV,
typename DerivedF,
typename DerivedSV,
typename DerivedSVI,
typename DerivedSVJ,
typename DerivedSF>
inline void remove_duplicate_vertices(
const Eigen::MatrixBase<DerivedV>& V,
const Eigen::MatrixBase<DerivedF>& F,
const double epsilon,
Eigen::PlainObjectBase<DerivedSV>& SV,
Eigen::PlainObjectBase<DerivedSVI>& SVI,
Eigen::PlainObjectBase<DerivedSVJ>& SVJ,
Eigen::PlainObjectBase<DerivedSF>& SF) {
// SVI and SVJ need to have RowsAtCompileTime == 1 or ColsAtCompileTime == 1
static_assert(
(DerivedSVI::RowsAtCompileTime == 1 || DerivedSVI::ColsAtCompileTime == 1) &&
(DerivedSVJ::RowsAtCompileTime == 1 || DerivedSVJ::ColsAtCompileTime == 1),
"SVI and SVJ need to have RowsAtCompileTime == 1 or ColsAtCompileTime == 1");
using namespace Eigen;
using namespace std;
remove_duplicate_vertices(V,epsilon,SV,SVI,SVJ);
SF.resizeLike(F);
int64_t fcount = 0;
for(int f = 0; f < F.rows(); f++) {
bool is_degen = false;
for(int c = 0; c < F.cols(); c++) {
for (int c2 = c + 1; c2 < F.cols(); c2++) {
if (SVJ(F(f,c)) == SVJ(F(f,c2))) {
is_degen = true;
break;
}
}
if (is_degen) {
break;
}
SF(fcount,c) = SVJ(F(f,c));
}
if (!is_degen) {
fcount++;
}
}
SF.conservativeResize(fcount, F.cols());
}


}





const char* remove_duplicate_points_doc = R"igl_Qu8mg5v7(
Removes duplicated points from a point cloud where two points are considered the same if their distance is below
some threshold
Expand Down Expand Up @@ -35,7 +118,7 @@ npe_begin_code()
Eigen::Matrix<int32_t, Eigen::Dynamic, 1> svj;
Eigen::Matrix<int32_t, Eigen::Dynamic, 1> svi;

igl::remove_duplicate_vertices(x_copy, epsilon, x_out, svi, svj);
remove_duplicate_vertices(x_copy, epsilon, x_out, svi, svj);

if (return_index) {
return pybind11::cast(std::make_tuple(npe::move(x_out), npe::move(svi), npe::move(svj)));
Expand Down Expand Up @@ -82,7 +165,7 @@ npe_begin_code()
Eigen::Matrix<int32_t, Eigen::Dynamic, 1> svi;
Eigen::Matrix<int32_t, Eigen::Dynamic, 1> svj;
igl::remove_duplicate_vertices(v_copy, f_copy, epsilon, v_out, svi, svj, f_out);
remove_duplicate_vertices(v_copy, f_copy, epsilon, v_out, svi, svj, f_out);
if (return_index) {
return pybind11::cast(std::make_tuple(npe::move(v_out), npe::move(f_out), npe::move(svi), npe::move(svj)));
Expand Down

0 comments on commit 3d7c8c4

Please sign in to comment.