Skip to content

Commit

Permalink
Add a new version of extrude_straigth_skeleton to generate building w…
Browse files Browse the repository at this point in the history
…ith roof
  • Loading branch information
lbartoletti committed Oct 3, 2023
1 parent 17f9566 commit af87944
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 18 deletions.
28 changes: 21 additions & 7 deletions src/algorithm/extrude.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ extrude(const Point &g, const Kernel::Vector_3 &v) -> LineString *;
auto
extrude(const LineString &g, const Kernel::Vector_3 &v) -> PolyhedralSurface *;
auto
extrude(const Polygon &g, const Kernel::Vector_3 &v) -> Solid *;
extrude(const Polygon &g, const Kernel::Vector_3 &v, bool addTop = true)
-> Solid *;
auto
extrude(const Triangle &g, const Kernel::Vector_3 &v) -> Solid *;

Expand Down Expand Up @@ -120,7 +121,7 @@ extrude(const LineString &g, const Kernel::Vector_3 &v) -> PolyhedralSurface *
///
///
auto
extrude(const Polygon &g, const Kernel::Vector_3 &v) -> Solid *
extrude(const Polygon &g, const Kernel::Vector_3 &v, bool addTop) -> Solid *
{
if (g.isEmpty()) {
return new Solid();
Expand All @@ -142,11 +143,12 @@ extrude(const Polygon &g, const Kernel::Vector_3 &v) -> Solid *
polyhedralSurface.addPolygon(bottom);

// "top"
Polygon top(bottom);
top.reverse();
translate(top, v);
polyhedralSurface.addPolygon(top);

if (addTop) {
Polygon top(bottom);
top.reverse();
translate(top, v);
polyhedralSurface.addPolygon(top);
}
// exterior ring and interior rings extruded
for (size_t i = 0; i < bottom.numRings(); i++) {
std::unique_ptr<PolyhedralSurface> boundaryExtruded(
Expand Down Expand Up @@ -391,5 +393,17 @@ extrude(const Geometry &g, const double &dx, const double &dy, const double &dz)
return extrude(g, Kernel::FT(dx), Kernel::FT(dy), Kernel::FT(dz));
}

SFCGAL_API auto
extrude(const Polygon &g, const double &height) -> std::unique_ptr<Geometry>
{

if (!std::isfinite(height)) {
BOOST_THROW_EXCEPTION(NonFiniteValueException(
"trying to extrude with non finite value in direction"));
}

return std::unique_ptr<Geometry>(
extrude(g, Kernel::Vector_3(0.0, 0.0, height), false));
}
} // namespace algorithm
} // namespace SFCGAL
2 changes: 2 additions & 0 deletions src/algorithm/extrude.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ SFCGAL_API std::unique_ptr<Geometry>
SFCGAL_API std::unique_ptr<Geometry>
extrude(const Geometry &g, const Kernel::Vector_3 &v);

SFCGAL_API std::unique_ptr<Geometry>
extrude(const Polygon &g, const double &height);
} // namespace algorithm
} // namespace SFCGAL

Expand Down
16 changes: 16 additions & 0 deletions src/algorithm/straightSkeleton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
#include <SFCGAL/MultiPolygon.h>
#include <SFCGAL/Polygon.h>
#include <SFCGAL/PolyhedralSurface.h>
#include <SFCGAL/Solid.h>
#include <SFCGAL/Triangle.h>

#include <SFCGAL/Exception.h>

#include <SFCGAL/algorithm/intersection.h>
#include <SFCGAL/algorithm/isValid.h>
#include <SFCGAL/algorithm/orientation.h>
#include <SFCGAL/algorithm/tesselate.h>
#include <SFCGAL/algorithm/translate.h>

#include <CGAL/Straight_skeleton_converter_2.h>
Expand Down Expand Up @@ -412,5 +414,19 @@ extrudeStraightSkeleton(const Geometry &g, double height)
return result;
}

auto
extrudeStraightSkeleton(const Geometry &g, double building_height,
double roof_height)
-> std::unique_ptr<PolyhedralSurface>
{
std::unique_ptr<PolyhedralSurface> roof{
extrudeStraightSkeleton(g, roof_height)};
translate(*roof, 0.0, 0.0, building_height);
std::unique_ptr<Geometry> building(extrude(g.as<Polygon>(), building_height));
std::unique_ptr<PolyhedralSurface> result{
new PolyhedralSurface(building->as<Solid>().exteriorShell())};
result->addPolygons(*roof);
return result;
};
} // namespace algorithm
} // namespace SFCGAL
10 changes: 9 additions & 1 deletion src/algorithm/straightSkeleton.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
#ifndef _SFCGAL_ALGORITHM_STRAIGHTSKELETON_H_
#define _SFCGAL_ALGORITHM_STRAIGHTSKELETON_H_

#include <SFCGAL/PolyhedralSurface.h>
#include <SFCGAL/algorithm/extrude.h>
#include <SFCGAL/algorithm/union.h>
#include <SFCGAL/config.h>

#include <memory>

namespace SFCGAL {
Expand Down Expand Up @@ -96,6 +98,12 @@ extrudedStraightSkeleton(const Polygon &g, double height)
SFCGAL_API auto
extrudeStraightSkeleton(const Geometry &g, double height)
-> std::unique_ptr<PolyhedralSurface>;

SFCGAL_API auto
extrudeStraightSkeleton(const Geometry &g, double building_height,
double roof_height)
-> std::unique_ptr<PolyhedralSurface>;

} // namespace algorithm
} // namespace SFCGAL

Expand Down
41 changes: 34 additions & 7 deletions src/capi/sfcgal_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1171,8 +1171,8 @@ sfcgal_geometry_has_validity_flag(const sfcgal_geometry_t *geom) -> int
}

extern "C" auto
sfcgal_geometry_extrude_straight_skeleton(const sfcgal_geometry_t *geom, double height)
-> sfcgal_geometry_t *
sfcgal_geometry_extrude_straight_skeleton(const sfcgal_geometry_t *geom,
double height) -> sfcgal_geometry_t *
{
const auto *g1 = reinterpret_cast<const SFCGAL::Geometry *>(geom);
std::unique_ptr<SFCGAL::PolyhedralSurface> polys;
Expand All @@ -1190,6 +1190,29 @@ sfcgal_geometry_extrude_straight_skeleton(const sfcgal_geometry_t *geom, double
return polys.release();
}

extern "C" auto
sfcgal_geometry_extrude_polygon_straight_skeleton(const sfcgal_geometry_t *geom,
double building_height,
double roof_height)
-> sfcgal_geometry_t *
{
const auto *g1 = reinterpret_cast<const SFCGAL::Geometry *>(geom);
std::unique_ptr<SFCGAL::Geometry> polys;

try {
polys = SFCGAL::algorithm::extrudeStraightSkeleton(*g1, building_height,
roof_height);
} catch (std::exception &e) {
SFCGAL_WARNING("During straight_extrude_skeleton_distance(A):");
SFCGAL_WARNING(" with A: %s",
((const SFCGAL::Geometry *)(geom))->asText().c_str());
SFCGAL_ERROR("%s", e.what());
return nullptr;
}

return polys.release();
}

extern "C" auto
sfcgal_geometry_straight_skeleton_distance_in_m(const sfcgal_geometry_t *geom)
-> sfcgal_geometry_t *
Expand Down Expand Up @@ -1279,15 +1302,15 @@ sfcgal_geometry_optimal_alpha_shapes(const sfcgal_geometry_t *geom,
return result.release();
}


extern "C" sfcgal_geometry_t *
sfcgal_y_monotone_partition_2(const sfcgal_geometry_t *geom)
{
const SFCGAL::Geometry *g1 = reinterpret_cast<const SFCGAL::Geometry *>(geom);
std::unique_ptr<SFCGAL::Geometry> result;

try {
result = SFCGAL::algorithm::partition_2(g1->as<const SFCGAL::Geometry>(), SFCGAL::algorithm::y_monotone);
result = SFCGAL::algorithm::partition_2(g1->as<const SFCGAL::Geometry>(),
SFCGAL::algorithm::y_monotone);
} catch (std::exception &e) {
SFCGAL_WARNING("During y_monotone_partition_2(A):");
SFCGAL_WARNING(" with A: %s",
Expand All @@ -1306,7 +1329,8 @@ sfcgal_approx_convex_partition_2(const sfcgal_geometry_t *geom)
std::unique_ptr<SFCGAL::Geometry> result;

try {
result = SFCGAL::algorithm::partition_2(g1->as<const SFCGAL::Geometry>(), SFCGAL::algorithm::approx_convex);
result = SFCGAL::algorithm::partition_2(g1->as<const SFCGAL::Geometry>(),
SFCGAL::algorithm::approx_convex);
} catch (std::exception &e) {
SFCGAL_WARNING("During approx_convex_partition_2(A):");
SFCGAL_WARNING(" with A: %s",
Expand All @@ -1325,7 +1349,9 @@ sfcgal_greene_approx_convex_partition_2(const sfcgal_geometry_t *geom)
std::unique_ptr<SFCGAL::Geometry> result;

try {
result = SFCGAL::algorithm::partition_2(g1->as<const SFCGAL::Geometry>(), SFCGAL::algorithm::greene_approx_convex);
result =
SFCGAL::algorithm::partition_2(g1->as<const SFCGAL::Geometry>(),
SFCGAL::algorithm::greene_approx_convex);
} catch (std::exception &e) {
SFCGAL_WARNING("During greene_approx_convex_partition_2(A):");
SFCGAL_WARNING(" with A: %s",
Expand All @@ -1343,7 +1369,8 @@ sfcgal_optimal_convex_partition_2(const sfcgal_geometry_t *geom)
std::unique_ptr<SFCGAL::Geometry> result;

try {
result = SFCGAL::algorithm::partition_2(g1->as<const SFCGAL::Geometry>(), SFCGAL::algorithm::optimal_convex);
result = SFCGAL::algorithm::partition_2(g1->as<const SFCGAL::Geometry>(),
SFCGAL::algorithm::optimal_convex);
} catch (std::exception &e) {
SFCGAL_WARNING("During optimal_convex_partition_2(A):");
SFCGAL_WARNING(" with A: %s",
Expand Down
12 changes: 9 additions & 3 deletions src/capi/sfcgal_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ typedef enum {
// TYPE_SURFACE = 14, //abstract
SFCGAL_TYPE_POLYHEDRALSURFACE = 15,
SFCGAL_TYPE_TRIANGULATEDSURFACE = 16,
SFCGAL_TYPE_TRIANGLE = 17,
SFCGAL_TYPE_TRIANGLE = 17,

//-- not official codes
SFCGAL_TYPE_SOLID = 101,
Expand Down Expand Up @@ -989,7 +989,12 @@ sfcgal_geometry_straight_skeleton_distance_in_m(const sfcgal_geometry_t *geom);
* @ingroup capi
*/
SFCGAL_API sfcgal_geometry_t *
sfcgal_geometry_extrude_straight_skeleton(const sfcgal_geometry_t *geom, double height);
sfcgal_geometry_extrude_straight_skeleton(const sfcgal_geometry_t *geom,
double height);
SFCGAL_API sfcgal_geometry_t *
sfcgal_geometry_extrude_polygon_straight_skeleton(const sfcgal_geometry_t *geom,
double building_height,
double roof_height);

/**
* Returns the approximate medial axis for the given Polygon
Expand Down Expand Up @@ -1075,7 +1080,8 @@ SFCGAL_API sfcgal_geometry_t *
sfcgal_approx_convex_partition_2(const sfcgal_geometry_t *geom);

/**
* Returns the greene approximal convex partition of a geometry (polygon without hole)
* Returns the greene approximal convex partition of a geometry (polygon without
* hole)
* @pre isValid(geom) == true
* @post isValid(return) == true
* @ingroup capi
Expand Down
66 changes: 66 additions & 0 deletions test/unit/SFCGAL/algorithm/StraightSkeletonTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,4 +351,70 @@ BOOST_AUTO_TEST_CASE(testExtrudeStraightSkeletonPolygonWithHole)
BOOST_CHECK_EQUAL(out->asText(2), expectedWKT);
}

BOOST_AUTO_TEST_CASE(testExtrudeStraightSkeletonGenerateBuilding)
{

std::unique_ptr<Geometry> g(
io::readWkt("POLYGON (( 0 0, 5 0, 5 5, 4 5, 4 4, 0 4, 0 0 ), (1 1, 1 2, "
"2 2, 2 1, 1 1))"));
std::unique_ptr<Geometry> out(
algorithm::extrudeStraightSkeleton(*g, 9.0, 2.0));
std::string expectedWKT(
"POLYHEDRALSURFACE Z(((0.00 0.00 0.00,0.00 4.00 0.00,4.00 4.00 0.00,4.00 "
"5.00 0.00,5.00 5.00 0.00,5.00 0.00 0.00,0.00 0.00 0.00),(1.00 1.00 "
"0.00,2.00 1.00 0.00,2.00 2.00 0.00,1.00 2.00 0.00,1.00 1.00 "
"0.00)),((0.00 0.00 0.00,0.00 0.00 9.00,0.00 4.00 9.00,0.00 4.00 "
"0.00,0.00 0.00 0.00)),((0.00 4.00 0.00,0.00 4.00 9.00,4.00 4.00 "
"9.00,4.00 4.00 0.00,0.00 4.00 0.00)),((4.00 4.00 0.00,4.00 4.00 "
"9.00,4.00 5.00 9.00,4.00 5.00 0.00,4.00 4.00 0.00)),((4.00 5.00 "
"0.00,4.00 5.00 9.00,5.00 5.00 9.00,5.00 5.00 0.00,4.00 5.00 "
"0.00)),((5.00 5.00 0.00,5.00 5.00 9.00,5.00 0.00 9.00,5.00 0.00 "
"0.00,5.00 5.00 0.00)),((5.00 0.00 0.00,5.00 0.00 9.00,0.00 0.00 "
"9.00,0.00 0.00 0.00,5.00 0.00 0.00)),((1.00 1.00 0.00,1.00 1.00 "
"9.00,2.00 1.00 9.00,2.00 1.00 0.00,1.00 1.00 0.00)),((2.00 1.00 "
"0.00,2.00 1.00 9.00,2.00 2.00 9.00,2.00 2.00 0.00,2.00 1.00 "
"0.00)),((2.00 2.00 0.00,2.00 2.00 9.00,1.00 2.00 9.00,1.00 2.00 "
"0.00,2.00 2.00 0.00)),((1.00 2.00 0.00,1.00 2.00 9.00,1.00 1.00 "
"9.00,1.00 1.00 0.00,1.00 2.00 0.00)),((4.00 5.00 9.00,5.00 5.00 "
"9.00,4.00 4.00 9.00,4.00 5.00 9.00)),((2.00 1.00 9.00,5.00 0.00 "
"9.00,0.00 0.00 9.00,2.00 1.00 9.00)),((5.00 5.00 9.00,5.00 0.00 "
"9.00,4.00 4.00 9.00,5.00 5.00 9.00)),((2.00 1.00 9.00,0.00 0.00 "
"9.00,1.00 1.00 9.00,2.00 1.00 9.00)),((1.00 2.00 9.00,1.00 1.00 "
"9.00,0.00 0.00 9.00,1.00 2.00 9.00)),((0.00 4.00 9.00,2.00 2.00 "
"9.00,1.00 2.00 9.00,0.00 4.00 9.00)),((0.00 4.00 9.00,1.00 2.00 "
"9.00,0.00 0.00 9.00,0.00 4.00 9.00)),((4.00 4.00 9.00,5.00 0.00 "
"9.00,2.00 2.00 9.00,4.00 4.00 9.00)),((4.00 4.00 9.00,2.00 2.00 "
"9.00,0.00 4.00 9.00,4.00 4.00 9.00)),((2.00 2.00 9.00,5.00 0.00 "
"9.00,2.00 1.00 9.00,2.00 2.00 9.00)),((0.50 2.50 9.50,0.00 0.00 "
"9.00,0.50 0.50 9.50,0.50 2.50 9.50)),((1.00 3.00 10.00,0.00 4.00 "
"9.00,0.50 2.50 9.50,1.00 3.00 10.00)),((0.50 2.50 9.50,0.00 4.00 "
"9.00,0.00 0.00 9.00,0.50 2.50 9.50)),((2.50 0.50 9.50,5.00 0.00 "
"9.00,3.50 1.50 10.50,2.50 0.50 9.50)),((0.00 0.00 9.00,5.00 0.00 "
"9.00,2.50 0.50 9.50,0.00 0.00 9.00)),((0.50 0.50 9.50,0.00 0.00 "
"9.00,2.50 0.50 9.50,0.50 0.50 9.50)),((4.50 3.50 9.50,5.00 5.00 "
"9.00,4.50 4.50 9.50,4.50 3.50 9.50)),((3.50 2.50 10.50,3.50 1.50 "
"10.50,4.50 3.50 9.50,3.50 2.50 10.50)),((4.50 3.50 9.50,5.00 0.00 "
"9.00,5.00 5.00 9.00,4.50 3.50 9.50)),((3.50 1.50 10.50,5.00 0.00 "
"9.00,4.50 3.50 9.50,3.50 1.50 10.50)),((5.00 5.00 9.00,4.00 5.00 "
"9.00,4.50 4.50 9.50,5.00 5.00 9.00)),((4.50 4.50 9.50,4.00 4.00 "
"9.00,4.50 3.50 9.50,4.50 4.50 9.50)),((4.50 4.50 9.50,4.00 5.00 "
"9.00,4.00 4.00 9.00,4.50 4.50 9.50)),((3.00 3.00 10.00,0.00 4.00 "
"9.00,1.00 3.00 10.00,3.00 3.00 10.00)),((3.50 2.50 10.50,4.50 3.50 "
"9.50,3.00 3.00 10.00,3.50 2.50 10.50)),((3.00 3.00 10.00,4.00 4.00 "
"9.00,0.00 4.00 9.00,3.00 3.00 10.00)),((4.50 3.50 9.50,4.00 4.00 "
"9.00,3.00 3.00 10.00,4.50 3.50 9.50)),((2.00 1.00 9.00,1.00 1.00 "
"9.00,0.50 0.50 9.50,2.00 1.00 9.00)),((2.50 0.50 9.50,2.00 1.00 "
"9.00,0.50 0.50 9.50,2.50 0.50 9.50)),((1.00 1.00 9.00,1.00 2.00 "
"9.00,0.50 2.50 9.50,1.00 1.00 9.00)),((0.50 0.50 9.50,1.00 1.00 "
"9.00,0.50 2.50 9.50,0.50 0.50 9.50)),((1.00 3.00 10.00,2.00 2.00 "
"9.00,3.00 3.00 10.00,1.00 3.00 10.00)),((0.50 2.50 9.50,1.00 2.00 "
"9.00,1.00 3.00 10.00,0.50 2.50 9.50)),((1.00 3.00 10.00,1.00 2.00 "
"9.00,2.00 2.00 9.00,1.00 3.00 10.00)),((2.00 2.00 9.00,2.00 1.00 "
"9.00,2.50 0.50 9.50,2.00 2.00 9.00)),((3.50 2.50 10.50,3.00 3.00 "
"10.00,3.50 1.50 10.50,3.50 2.50 10.50)),((3.50 1.50 10.50,2.00 2.00 "
"9.00,2.50 0.50 9.50,3.50 1.50 10.50)),((3.00 3.00 10.00,2.00 2.00 "
"9.00,3.50 1.50 10.50,3.00 3.00 10.00)))");
BOOST_CHECK_EQUAL(out->asText(2), expectedWKT);
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit af87944

Please sign in to comment.