Skip to content

Commit 418b4c2

Browse files
committed
create_offset_polygons_with_holes_2
1 parent 0b9336e commit 418b4c2

5 files changed

+206
-80
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
* Added recipe hasher.
1313
* Added `scip` to dev install instructions in README.md
14+
* Added `compas_cgal.straight_skeleton_2.create_offset_polygons_with_holes_2`.
1415

1516
### Changed
1617

src/compas_cgal/straight_skeleton_2.py

+57
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,63 @@ def create_offset_polygons_2(points, offset) -> list[Polygon]:
155155
return [Polygon(points.tolist()) for points in offset_polygons]
156156

157157

158+
def create_offset_polygons_with_holes_2(points, holes, offset) -> list[Tuple[Polygon, list[Polygon]]]:
159+
"""Compute the polygon offset with holes.
160+
161+
Parameters
162+
----------
163+
points : list of point coordinates or :class:`compas.geometry.Polygon`
164+
The points of the polygon.
165+
holes : list of list of point coordinates or list of :class:`compas.geometry.Polygon`
166+
The holes of the polygon.
167+
offset : float
168+
The offset distance. If negative, the offset is outside the polygon, otherwise inside.
169+
170+
Returns
171+
-------
172+
173+
Returns
174+
-------
175+
list of tuple of (:class:`Polygon`, list[:class:`Polygon`])
176+
The polygons with holes.
177+
178+
Raises
179+
------
180+
ValueError
181+
If the normal of the polygon is not [0, 0, 1].
182+
If the normal of a hole is not [0, 0, -1].
183+
"""
184+
points = list(points)
185+
normal = normal_polygon(points, True)
186+
if not TOL.is_allclose(normal, [0, 0, 1]):
187+
raise ValueError("The normal of the polygon should be [0, 0, 1]. The normal of the provided polygon is {}".format(normal))
188+
V = np.asarray(points, dtype=np.float64)
189+
190+
H = []
191+
for i, hole in enumerate(holes):
192+
points = list(hole)
193+
normal_hole = normal_polygon(points, True)
194+
if not TOL.is_allclose(normal_hole, [0, 0, -1]):
195+
raise ValueError("The normal of the hole should be [0, 0, -1]. The normal of the provided {}-th hole is {}".format(i, normal_hole))
196+
hole = np.asarray(points, dtype=np.float64)
197+
H.append(hole)
198+
199+
offset = float(offset)
200+
if offset < 0: # outside
201+
offset_polygons = straight_skeleton_2.create_offset_polygons_2_outer_with_holes(V, H, abs(offset))
202+
else: # inside
203+
offset_polygons = straight_skeleton_2.create_offset_polygons_2_inner_with_holes(V, H, offset)
204+
205+
result = []
206+
for points, holes_np in offset_polygons:
207+
polygon = Polygon(points.tolist())
208+
holes = []
209+
for hole in holes_np:
210+
holes.append(Polygon(hole.tolist()))
211+
result.append((polygon, holes))
212+
return result
213+
214+
158215
def create_weighted_offset_polygons_2(points, offset, weights) -> list[Polygon]:
159216
"""Compute the polygon offset with weights.
160217

src/straight_skeleton_2.cpp

+100-80
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <CGAL/create_offset_polygons_2.h>
77
#include <CGAL/create_weighted_offset_polygons_from_polygon_with_holes_2.h>
88
#include <CGAL/create_weighted_straight_skeleton_2.h>
9+
#include <CGAL/create_offset_polygons_from_polygon_with_holes_2.h>
910

1011
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
1112
typedef K::Point_2 Point;
@@ -17,6 +18,8 @@ typedef CGAL::Straight_skeleton_2<K>::Halfedge_const_handle Halfedge_const_handl
1718
typedef CGAL::Straight_skeleton_2<K>::Vertex_const_handle Vertex_const_handle;
1819
typedef boost::shared_ptr<Polygon_2> PolygonPtr;
1920
typedef std::vector<PolygonPtr> PolygonPtrVector;
21+
typedef boost::shared_ptr<Polygon_with_holes> PolygonWithHolesPtr;
22+
typedef std::vector<PolygonWithHolesPtr> PolygonWithHolesPtrVector;
2023

2124

2225
std::tuple<compas::RowMatrixXd, std::vector<int>, compas::RowMatrixXi, std::vector<int>> mesh_data_from_skeleton(boost::shared_ptr<Ss> &iss){
@@ -62,97 +65,119 @@ std::tuple<compas::RowMatrixXd, std::vector<int>, compas::RowMatrixXi, std::vect
6265
return result;
6366
}
6467

65-
std::tuple<compas::RowMatrixXd, std::vector<int>, compas::RowMatrixXi, std::vector<int>> pmp_create_interior_straight_skeleton(
66-
Eigen::Ref<const compas::RowMatrixXd> &V)
67-
{
68-
Polygon_2 poly;
69-
for (int i = 0; i < V.rows(); i++)
70-
{
71-
poly.push_back(Point(V(i, 0), V(i, 1)));
68+
compas::RowMatrixXd polygon_to_data(Polygon_2 const& poly){
69+
std::size_t n = poly.size();
70+
compas::RowMatrixXd points(n, 3);
71+
int j = 0;
72+
for(typename Polygon_2::Vertex_const_iterator vi = poly.vertices_begin() ; vi != poly.vertices_end() ; ++ vi){
73+
points(j, 0) = (double)(*vi).x();
74+
points(j, 1) = (double)(*vi).y();
75+
points(j, 2) = 0;
76+
j++;
7277
}
73-
SsPtr iss = CGAL::create_interior_straight_skeleton_2(poly.vertices_begin(), poly.vertices_end());
78+
return points;
79+
}
7480

75-
return mesh_data_from_skeleton(iss);
76-
};
81+
std::tuple<compas::RowMatrixXd, std::vector<compas::RowMatrixXd>> polygon_with_holes_to_data(Polygon_with_holes const& polywh){
82+
std::vector<compas::RowMatrixXd> holes;
83+
compas::RowMatrixXd points = polygon_to_data(polywh.outer_boundary());
84+
for(typename Polygon_with_holes::Hole_const_iterator hi = polywh.holes_begin() ; hi != polywh.holes_end() ; ++ hi){
85+
compas::RowMatrixXd hole = polygon_to_data(*hi);
86+
holes.push_back(hole);
87+
}
88+
std::tuple<compas::RowMatrixXd, std::vector<compas::RowMatrixXd>> result = std::make_tuple(points, holes);
89+
return result;
90+
}
7791

78-
std::tuple<compas::RowMatrixXd, std::vector<int>, compas::RowMatrixXi, std::vector<int>> pmp_create_interior_straight_skeleton_with_holes(
79-
Eigen::Ref<const compas::RowMatrixXd> &V,
80-
std::vector<Eigen::Ref<const compas::RowMatrixXd>> &holes)
81-
{
82-
Polygon_2 outer;
83-
for (int i = 0; i < V.rows(); i++)
84-
{
85-
outer.push_back(Point(V(i, 0), V(i, 1)));
92+
Polygon_2 data_to_polygon(Eigen::Ref<const compas::RowMatrixXd> &V){
93+
Polygon_2 poly;
94+
for (int i = 0; i < V.rows(); i++){
95+
poly.push_back(Point(V(i, 0), V(i, 1)));
8696
}
87-
Polygon_with_holes poly(outer);
97+
return poly;
98+
}
8899

89-
for (auto hit : holes)
90-
{
100+
Polygon_with_holes data_to_polygon_with_holes(Eigen::Ref<const compas::RowMatrixXd> &V, std::vector<Eigen::Ref<const compas::RowMatrixXd>> &holes){
101+
Polygon_2 outer = data_to_polygon(V);
102+
Polygon_with_holes poly(outer);
103+
for (auto hit : holes){
91104
compas::RowMatrixXd H = hit;
105+
//Polygon_2 hole = data_to_polygon(*H); // why does this not work?
92106
Polygon_2 hole;
93-
for (int i = 0; i < H.rows(); i++)
94-
{
107+
for (int i = 0; i < H.rows(); i++){
95108
hole.push_back(Point(H(i, 0), H(i, 1)));
96109
}
97110
poly.add_hole(hole);
98-
99111
}
112+
return poly;
113+
}
100114

115+
std::tuple<compas::RowMatrixXd, std::vector<int>, compas::RowMatrixXi, std::vector<int>> pmp_create_interior_straight_skeleton(
116+
Eigen::Ref<const compas::RowMatrixXd> &V){
117+
Polygon_2 poly = data_to_polygon(V);
118+
SsPtr iss = CGAL::create_interior_straight_skeleton_2(poly.vertices_begin(), poly.vertices_end());
119+
return mesh_data_from_skeleton(iss);
120+
};
121+
122+
std::tuple<compas::RowMatrixXd, std::vector<int>, compas::RowMatrixXi, std::vector<int>> pmp_create_interior_straight_skeleton_with_holes(
123+
Eigen::Ref<const compas::RowMatrixXd> &V,
124+
std::vector<Eigen::Ref<const compas::RowMatrixXd>> &holes){
125+
Polygon_with_holes poly = data_to_polygon_with_holes(V, holes);
101126
SsPtr iss = CGAL::create_interior_straight_skeleton_2(poly);
102127
return mesh_data_from_skeleton(iss);
103128
}
104129

105130
std::vector<compas::RowMatrixXd> pmp_create_offset_polygons_2_inner(Eigen::Ref<const compas::RowMatrixXd> &V, double &offset){
106-
Polygon_2 poly;
107-
for (int i = 0; i < V.rows(); i++){
108-
poly.push_back(Point(V(i, 0), V(i, 1)));
109-
}
131+
Polygon_2 poly = data_to_polygon(V);
110132
PolygonPtrVector offset_polygons = CGAL::create_interior_skeleton_and_offset_polygons_2(offset, poly);
111133

112134
std::vector<compas::RowMatrixXd> result;
113-
for(auto pi = offset_polygons.begin(); pi != offset_polygons.end(); ++pi){
114-
std::size_t n = (*pi)->size();
115-
compas::RowMatrixXd points(n, 3);
116-
int j = 0;
117-
for (auto vi = (*pi)->vertices_begin(); vi != (*pi)->vertices_end(); ++vi){
118-
points(j, 0) = (double)(*vi).x();
119-
points(j, 1) = (double)(*vi).y();
120-
points(j, 2) = 0;
121-
j++;
122-
}
135+
for(typename PolygonPtrVector::const_iterator pi = offset_polygons.begin() ; pi != offset_polygons.end() ; ++ pi ){
136+
compas::RowMatrixXd points = polygon_to_data(**pi);
123137
result.push_back(points);
124138
}
125139
return result;
126140
}
127141

128-
std::vector<compas::RowMatrixXd> pmp_create_offset_polygons_2_outer(Eigen::Ref<const compas::RowMatrixXd> &V, double &offset){
129-
Polygon_2 poly;
130-
for (int i = 0; i < V.rows(); i++){
131-
poly.push_back(Point(V(i, 0), V(i, 1)));
142+
std::vector<std::tuple<compas::RowMatrixXd, std::vector<compas::RowMatrixXd>>> pmp_create_offset_polygons_2_inner_with_holes(Eigen::Ref<const compas::RowMatrixXd> &V, std::vector<Eigen::Ref<const compas::RowMatrixXd>> &holes, double &offset){
143+
144+
Polygon_with_holes poly = data_to_polygon_with_holes(V, holes);
145+
PolygonWithHolesPtrVector offset_polygons = CGAL::create_interior_skeleton_and_offset_polygons_with_holes_2(offset, poly);
146+
147+
std::vector<std::tuple<compas::RowMatrixXd, std::vector<compas::RowMatrixXd>>> result;
148+
for(typename PolygonWithHolesPtrVector::const_iterator pi = offset_polygons.begin() ; pi != offset_polygons.end() ; ++ pi ){
149+
std::tuple<compas::RowMatrixXd, std::vector<compas::RowMatrixXd>> polywh_data = polygon_with_holes_to_data(**pi);
150+
result.push_back(polywh_data);
132151
}
152+
return result;
153+
}
154+
155+
std::vector<compas::RowMatrixXd> pmp_create_offset_polygons_2_outer(Eigen::Ref<const compas::RowMatrixXd> &V, double &offset){
156+
Polygon_2 poly = data_to_polygon(V);
133157
PolygonPtrVector offset_polygons = CGAL::create_exterior_skeleton_and_offset_polygons_2(offset, poly);
134158

135159
std::vector<compas::RowMatrixXd> result;
136-
for(auto pi = offset_polygons.begin(); pi != offset_polygons.end(); ++pi){
137-
std::size_t n = (*pi)->size();
138-
compas::RowMatrixXd points(n, 3);
139-
int j = 0;
140-
for (auto vi = (*pi)->vertices_begin(); vi != (*pi)->vertices_end(); ++vi){
141-
points(j, 0) = (double)(*vi).x();
142-
points(j, 1) = (double)(*vi).y();
143-
points(j, 2) = 0;
144-
j++;
145-
}
160+
for(typename PolygonPtrVector::const_iterator pi = offset_polygons.begin() ; pi != offset_polygons.end() ; ++ pi ){
161+
compas::RowMatrixXd points = polygon_to_data(**pi);
146162
result.push_back(points);
147163
}
148164
return result;
149165
}
150166

151-
std::vector<compas::RowMatrixXd> pmp_create_weighted_offset_polygons_2_inner(Eigen::Ref<const compas::RowMatrixXd> &V, double &offset, Eigen::Ref<const compas::RowMatrixXd> &weights){
152-
Polygon_2 poly;
153-
for (int i = 0; i < V.rows(); i++){
154-
poly.push_back(Point(V(i, 0), V(i, 1)));
167+
std::vector<std::tuple<compas::RowMatrixXd, std::vector<compas::RowMatrixXd>>> pmp_create_offset_polygons_2_outer_with_holes(Eigen::Ref<const compas::RowMatrixXd> &V, std::vector<Eigen::Ref<const compas::RowMatrixXd>> &holes, double &offset){
168+
Polygon_with_holes poly = data_to_polygon_with_holes(V, holes);
169+
PolygonWithHolesPtrVector offset_polygons = CGAL::create_exterior_skeleton_and_offset_polygons_with_holes_2(offset, poly);
170+
171+
std::vector<std::tuple<compas::RowMatrixXd, std::vector<compas::RowMatrixXd>>> result;
172+
for(typename PolygonWithHolesPtrVector::const_iterator pi = offset_polygons.begin() ; pi != offset_polygons.end() ; ++ pi ){
173+
std::tuple<compas::RowMatrixXd, std::vector<compas::RowMatrixXd>> polywh_data = polygon_with_holes_to_data(**pi);
174+
result.push_back(polywh_data);
155175
}
176+
return result;
177+
}
178+
179+
std::vector<compas::RowMatrixXd> pmp_create_weighted_offset_polygons_2_inner(Eigen::Ref<const compas::RowMatrixXd> &V, double &offset, Eigen::Ref<const compas::RowMatrixXd> &weights){
180+
Polygon_2 poly = data_to_polygon(V);
156181
std::vector<double> weights_vec;
157182
for (int i = 0; i < weights.rows(); i++){
158183
weights_vec.push_back(weights(i, 0));
@@ -161,26 +186,15 @@ std::vector<compas::RowMatrixXd> pmp_create_weighted_offset_polygons_2_inner(Eig
161186
PolygonPtrVector offset_polygons = CGAL::create_offset_polygons_2<Polygon_2>(offset, *iss);
162187

163188
std::vector<compas::RowMatrixXd> result;
164-
for(auto pi = offset_polygons.begin(); pi != offset_polygons.end(); ++pi){
165-
std::size_t n = (*pi)->size();
166-
compas::RowMatrixXd points(n, 3);
167-
int j = 0;
168-
for (auto vi = (*pi)->vertices_begin(); vi != (*pi)->vertices_end(); ++vi){
169-
points(j, 0) = (double)(*vi).x();
170-
points(j, 1) = (double)(*vi).y();
171-
points(j, 2) = 0;
172-
j++;
173-
}
189+
for(typename PolygonPtrVector::const_iterator pi = offset_polygons.begin() ; pi != offset_polygons.end() ; ++ pi ){
190+
compas::RowMatrixXd points = polygon_to_data(**pi);
174191
result.push_back(points);
175192
}
176193
return result;
177194
}
178195

179196
std::vector<compas::RowMatrixXd> pmp_create_weighted_offset_polygons_2_outer(Eigen::Ref<const compas::RowMatrixXd> &V, double &offset, Eigen::Ref<const compas::RowMatrixXd> &weights){
180-
Polygon_2 poly;
181-
for (int i = 0; i < V.rows(); i++){
182-
poly.push_back(Point(V(i, 0), V(i, 1)));
183-
}
197+
Polygon_2 poly = data_to_polygon(V);
184198
std::vector<double> weights_vec;
185199
for (int i = 0; i < weights.rows(); i++){
186200
weights_vec.push_back(weights(i, 0));
@@ -189,16 +203,8 @@ std::vector<compas::RowMatrixXd> pmp_create_weighted_offset_polygons_2_outer(Eig
189203
PolygonPtrVector offset_polygons = CGAL::create_offset_polygons_2<Polygon_2>(offset, *iss);
190204

191205
std::vector<compas::RowMatrixXd> result;
192-
for(auto pi = offset_polygons.begin(); pi != offset_polygons.end(); ++pi){
193-
std::size_t n = (*pi)->size();
194-
compas::RowMatrixXd points(n, 3);
195-
int j = 0;
196-
for (auto vi = (*pi)->vertices_begin(); vi != (*pi)->vertices_end(); ++vi){
197-
points(j, 0) = (double)(*vi).x();
198-
points(j, 1) = (double)(*vi).y();
199-
points(j, 2) = 0;
200-
j++;
201-
}
206+
for(typename PolygonPtrVector::const_iterator pi = offset_polygons.begin() ; pi != offset_polygons.end() ; ++ pi ){
207+
compas::RowMatrixXd points = polygon_to_data(**pi);
202208
result.push_back(points);
203209
}
204210
return result;
@@ -229,12 +235,26 @@ void init_straight_skeleton_2(pybind11::module &m)
229235
pybind11::arg("V").noconvert(),
230236
pybind11::arg("offset").noconvert());
231237

238+
submodule.def(
239+
"create_offset_polygons_2_inner_with_holes",
240+
&pmp_create_offset_polygons_2_inner_with_holes,
241+
pybind11::arg("V").noconvert(),
242+
pybind11::arg("holes").noconvert(),
243+
pybind11::arg("offset").noconvert());
244+
232245
submodule.def(
233246
"create_offset_polygons_2_outer",
234247
&pmp_create_offset_polygons_2_outer,
235248
pybind11::arg("V").noconvert(),
236249
pybind11::arg("offset").noconvert());
237250

251+
submodule.def(
252+
"create_offset_polygons_2_outer_with_holes",
253+
&pmp_create_offset_polygons_2_outer_with_holes,
254+
pybind11::arg("V").noconvert(),
255+
pybind11::arg("holes").noconvert(),
256+
pybind11::arg("offset").noconvert());
257+
238258
submodule.def(
239259
"create_weighted_offset_polygons_2_inner",
240260
&pmp_create_weighted_offset_polygons_2_inner,

src/straight_skeleton_2.h

+10
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,20 @@ std::vector<compas::RowMatrixXd> pmp_create_offset_polygons_2_inner(
1616
Eigen::Ref<const compas::RowMatrixXd> &V,
1717
double &offset);
1818

19+
std::vector<std::tuple<compas::RowMatrixXd, std::vector<compas::RowMatrixXd>>> pmp_create_offset_polygons_2_inner_with_holes(
20+
Eigen::Ref<const compas::RowMatrixXd> &V,
21+
std::vector<Eigen::Ref<const compas::RowMatrixXd>> &holes,
22+
double &offset);
23+
1924
std::vector<compas::RowMatrixXd> pmp_create_offset_polygons_2_outer(
2025
Eigen::Ref<const compas::RowMatrixXd> &V,
2126
double &offset);
2227

28+
std::vector<std::tuple<compas::RowMatrixXd, std::vector<compas::RowMatrixXd>>> pmp_create_offset_polygons_2_outer_with_holes(
29+
Eigen::Ref<const compas::RowMatrixXd> &V,
30+
std::vector<Eigen::Ref<const compas::RowMatrixXd>> &holes,
31+
double &offset);
32+
2333
std::vector<compas::RowMatrixXd> pmp_create_weighted_offset_polygons_2_inner(
2434
Eigen::Ref<const compas::RowMatrixXd> &V,
2535
double &offset,

0 commit comments

Comments
 (0)