Skip to content

Commit

Permalink
adding inner and outer offsets
Browse files Browse the repository at this point in the history
  • Loading branch information
romanarust committed Jul 3, 2024
1 parent fc60f46 commit 4310a02
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 2 deletions.
36 changes: 36 additions & 0 deletions docs/examples/straight_skeleton_offset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from compas.datastructures import Graph
from compas.geometry import Polygon
from compas_cgal.straight_skeleton_2 import create_offset_polygons_2
from compas_viewer import Viewer

points = [
(-1.91, 3.59, 0.0),
(-5.53, -5.22, 0.0),
(-0.39, -1.98, 0.0),
(2.98, -5.51, 0.0),
(4.83, -2.02, 0.0),
(9.70, -3.63, 0.0),
(12.23, 1.25, 0.0),
(3.42, 0.66, 0.0),
(2.92, 4.03, 0.0),
(-1.91, 3.59, 0.0),
]
polygon = Polygon(points)
offset = 1.5

offset_polygons_inner = create_offset_polygons_2(points, offset)
offset_polygons_outer = create_offset_polygons_2(points, -offset)

# ==============================================================================
# Viz
# ==============================================================================

viewer = Viewer(width=1600, height=900)
viewer.scene.add(polygon)

for opolygon in offset_polygons_inner:
viewer.scene.add(opolygon, linecolor=(1.0, 0.0, 0.0))
for opolygon in offset_polygons_outer:
viewer.scene.add(opolygon, linecolor=(0.0, 0.0, 1.0))

viewer.show()
15 changes: 15 additions & 0 deletions src/compas_cgal/straight_skeleton_2.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import numpy as np
from compas.geometry import normal_polygon
from compas.geometry import Polygon
from compas.tolerance import TOL

from compas_cgal._cgal import straight_skeleton_2
Expand Down Expand Up @@ -66,3 +67,17 @@ def create_interior_straight_skeleton_with_holes(points, holes) -> PolylinesNump
hole = np.asarray(points, dtype=np.float64)
H.append(hole)
return straight_skeleton_2.create_interior_straight_skeleton_with_holes(V, H)


def create_offset_polygons_2(points, offset) -> PolylinesNumpy:
points = list(points)
if not TOL.is_allclose(normal_polygon(points, True), [0, 0, 1]):
raise ValueError("Please pass a polygon with a normal vector of [0, 0, 1].")
V = np.asarray(points, dtype=np.float64)
offset = float(offset)
if offset < 0: # outside
offset_polygons = straight_skeleton_2.create_offset_polygons_2_outer(V, abs(offset))[1:] # first one is box
else: # inside
offset_polygons = straight_skeleton_2.create_offset_polygons_2_inner(V, offset)
return [Polygon(points.tolist()) for points in offset_polygons]

61 changes: 61 additions & 0 deletions src/straight_skeleton_2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <CGAL/Polygon_2.h>
#include <CGAL/create_straight_skeleton_2.h>
#include <CGAL/create_straight_skeleton_from_polygon_with_holes_2.h>
#include <CGAL/create_offset_polygons_2.h>

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point;
Expand All @@ -12,6 +13,8 @@ typedef CGAL::Straight_skeleton_2<K> Ss;
typedef boost::shared_ptr<Ss> SsPtr;
typedef CGAL::Straight_skeleton_2<K>::Halfedge_const_handle Halfedge_const_handle;
typedef CGAL::Straight_skeleton_2<K>::Vertex_const_handle Vertex_const_handle;
typedef boost::shared_ptr<Polygon_2> PolygonPtr;
typedef std::vector<PolygonPtr> PolygonPtrVector;

compas::Edges pmp_create_interior_straight_skeleton(
Eigen::Ref<const compas::RowMatrixXd> &V)
Expand Down Expand Up @@ -86,6 +89,52 @@ compas::Edges pmp_create_interior_straight_skeleton_with_holes(

}

std::vector<compas::RowMatrixXd> pmp_create_offset_polygons_2_inner(Eigen::Ref<const compas::RowMatrixXd> &V, double &offset){
Polygon_2 poly;
for (int i = 0; i < V.rows(); i++){
poly.push_back(Point(V(i, 0), V(i, 1)));
}
PolygonPtrVector offset_polygons = CGAL::create_interior_skeleton_and_offset_polygons_2(offset, poly);

std::vector<compas::RowMatrixXd> result;
for(auto pi = offset_polygons.begin(); pi != offset_polygons.end(); ++pi){
std::size_t n = (*pi)->size();
compas::RowMatrixXd points(n, 3);
int j = 0;
for (auto vi = (*pi)->vertices_begin(); vi != (*pi)->vertices_end(); ++vi){
points(j, 0) = (double)(*vi).x();
points(j, 1) = (double)(*vi).y();
points(j, 2) = 0;
j++;
}
result.push_back(points);
}
return result;
}

std::vector<compas::RowMatrixXd> pmp_create_offset_polygons_2_outer(Eigen::Ref<const compas::RowMatrixXd> &V, double &offset){
Polygon_2 poly;
for (int i = 0; i < V.rows(); i++){
poly.push_back(Point(V(i, 0), V(i, 1)));
}
PolygonPtrVector offset_polygons = CGAL::create_exterior_skeleton_and_offset_polygons_2(offset, poly);

std::vector<compas::RowMatrixXd> result;
for(auto pi = offset_polygons.begin(); pi != offset_polygons.end(); ++pi){
std::size_t n = (*pi)->size();
compas::RowMatrixXd points(n, 3);
int j = 0;
for (auto vi = (*pi)->vertices_begin(); vi != (*pi)->vertices_end(); ++vi){
points(j, 0) = (double)(*vi).x();
points(j, 1) = (double)(*vi).y();
points(j, 2) = 0;
j++;
}
result.push_back(points);
}
return result;
}

// ===========================================================================
// PyBind11
// ===========================================================================
Expand All @@ -104,4 +153,16 @@ void init_straight_skeleton_2(pybind11::module &m)
&pmp_create_interior_straight_skeleton_with_holes,
pybind11::arg("V").noconvert(),
pybind11::arg("holes").noconvert());

submodule.def(
"create_offset_polygons_2_inner",
&pmp_create_offset_polygons_2_inner,
pybind11::arg("V").noconvert(),
pybind11::arg("offset").noconvert());

submodule.def(
"create_offset_polygons_2_outer",
&pmp_create_offset_polygons_2_outer,
pybind11::arg("V").noconvert(),
pybind11::arg("offset").noconvert());
};
9 changes: 8 additions & 1 deletion src/straight_skeleton_2.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@
compas::Edges pmp_create_interior_straight_skeleton(
Eigen::Ref<const compas::RowMatrixXd> &V);


compas::Edges pmp_create_interior_straight_skeleton_with_holes(
Eigen::Ref<const compas::RowMatrixXd> &V,
std::vector<Eigen::Ref<const compas::RowMatrixXd>> &holes);

std::vector<compas::RowMatrixXd> pmp_create_offset_polygons_2_inner(
Eigen::Ref<const compas::RowMatrixXd> &V,
double &offset);

std::vector<compas::RowMatrixXd> pmp_create_offset_polygons_2_outer(
Eigen::Ref<const compas::RowMatrixXd> &V,
double &offset);

#endif /* COMPAS_STRAIGHT_SKELETON_2_H */
20 changes: 19 additions & 1 deletion tests/test_straight_skeleton_2.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from compas_cgal.straight_skeleton_2 import create_interior_straight_skeleton
from compas_cgal.straight_skeleton_2 import create_interior_straight_skeleton_with_holes

from compas_cgal.straight_skeleton_2 import create_offset_polygons_2

def test_straight_polygon():
points = [
Expand Down Expand Up @@ -73,3 +73,21 @@ def test_straight_polygon_2_compare():
# the line direction sometimes changes ...
assert TOL.is_allclose(sa, se) or TOL.is_allclose(sa, ee)
assert TOL.is_allclose(ea, ee) or TOL.is_allclose(ea, se)


def test_offset():
points = [
(-1, -1, 0),
(0, -12, 0),
(1, -1, 0),
(12, 0, 0),
(1, 1, 0),
(0, 12, 0),
(-1, 1, 0),
(-12, 0, 0),
]
offset = 0.5
polygons = create_offset_polygons_2(points, offset)
assert len(polygons) == 1, len(polygons)
polygons = create_offset_polygons_2(points, -offset)
assert len(polygons) == 1, len(polygons)

0 comments on commit 4310a02

Please sign in to comment.