Skip to content
This repository has been archived by the owner on Mar 25, 2024. It is now read-only.

Issue 200 fix intersection #201

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 48 additions & 3 deletions src/algorithm/Intersection3D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@

#include <SFCGAL/detail/Point_inside_polyhedron.h>

#include <CGAL/Nef_polyhedron_3.h>
#include <CGAL/IO/Nef_polyhedron_iostream_3.h>
#include <CGAL/Nef_3/SNC_indexed_items.h>
#include <CGAL/convex_decomposition_3.h>

using namespace SFCGAL::detail;

namespace SFCGAL {
Expand Down Expand Up @@ -320,9 +325,49 @@ void _intersection_solid_solid( const MarkedPolyhedron& pa, const MarkedPolyhedr
}

// else, we have an intersection
MarkedPolyhedron* res_poly = result[0].first;
output.addPrimitive( *res_poly );
delete res_poly;
std::vector<std::unique_ptr<MarkedPolyhedron>> res_poly;
res_poly.reserve(result.size());

Decomposition::const_iterator end_citer = result.cend();
for ( Decomposition::const_iterator citer = result.cbegin(); citer != end_citer; ++citer ) {
res_poly.push_back( std::unique_ptr<MarkedPolyhedron>( citer->first ) );
}

// Decompose the intersection geometry into separate
// convex parts.
using Nef_polyhedron_3
= CGAL::Nef_polyhedron_3<SFCGAL::Kernel, CGAL::SNC_indexed_items>;

Nef_polyhedron_3 N( *res_poly[0] );

CGAL::convex_decomposition_3( N );
std::list<MarkedPolyhedron> convex_parts;

// The first volume is the outer volume, which should be
// ignored in the decomposition, so we skip it.
using Volume_const_iterator = Nef_polyhedron_3::Volume_const_iterator;

Volume_const_iterator ci = ++N.volumes_begin();
while ( ci != N.volumes_end() ) {
if ( ci->mark() ) {
MarkedPolyhedron P;
N.convert_inner_shell_to_polyhedron( ci->shells_begin(), P );
convex_parts.push_back( P );
}

++ci;
}

// Add convex parts to output geometry collection.
if ( convex_parts.size() == 1 ) {
// Don't bother copying the original Polyhedron
// if it is the only part.
output.addPrimitive( *res_poly[0] );
} else {
for ( const MarkedPolyhedron& mp : convex_parts ) {
output.addPrimitive( mp );
}
}
}
}

Expand Down
27 changes: 25 additions & 2 deletions src/detail/GeometrySet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,7 @@ void _filter_covered( IT ibegin, IT iend, GeometrySet<Dim>& output )
for ( IT it = ibegin; it != iend; ++it ) {
GeometrySet<Dim> v1;
v1.addPrimitive( it->primitive() );
std::unique_ptr<Geometry> g1 = v1.recompose();
bool v1_covered = false;

for ( IT it2 = it; it2 != iend; ++it2 ) {
Expand All @@ -937,7 +938,19 @@ void _filter_covered( IT ibegin, IT iend, GeometrySet<Dim>& output )
GeometrySet<Dim> v2;
v2.addPrimitive( it2->primitive() );

if ( algorithm::covers( v2, v1 ) ) {
bool b = false;
if ( g1->is3D() ) {
std::unique_ptr<Geometry> g2 = v2.recompose();
if ( g2->is3D() ) {
b = algorithm::covers3D( *g1, *g2 );
} else {
b = algorithm::covers( v2, v1 );
}
} else {
b = algorithm::covers( v2, v1 );
}

if (b) {
v1_covered = true;
break;
}
Expand All @@ -946,7 +959,17 @@ void _filter_covered( IT ibegin, IT iend, GeometrySet<Dim>& output )
// if its not covered by another primitive
if ( !v1_covered ) {
// and not covered by another already inserted primitive
bool b = algorithm::covers( output, v1 );
bool b = false;
if ( g1->is3D() ) {
std::unique_ptr<Geometry> goutput = output.recompose();
if ( goutput->is3D() ) {
b = algorithm::covers3D( *goutput, *g1 );
} else {
b = algorithm::covers( output, v1 );
}
} else {
b = algorithm::covers( output, v1 );
}

if ( !b ) {
output.addPrimitive( it->primitive(), it->flags() );
Expand Down
2 changes: 1 addition & 1 deletion test/bench/BenchWKT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ BOOST_AUTO_TEST_CASE( testReadTriangle )
bench().start( boost::format( "READ WKT TRIANGLE" ) ) ;

for ( int i = 0; i < N; i++ ) {
io::readWkt( "TRIANGLE((0 0,0 1000,1000 1000,1000 0,0 0))" ) ;
io::readWkt( "TRIANGLE((0 0,0 1000,1000 1000,0 0))" ) ;
}

bench().stop();
Expand Down
87 changes: 86 additions & 1 deletion test/unit/SFCGAL/algorithm/IntersectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <SFCGAL/MultiPolygon.h>
#include <SFCGAL/MultiSolid.h>
#include <SFCGAL/detail/transform/AffineTransform3.h>
#include <SFCGAL/algorithm/extrude.h>

#include "../../../test_config.h"

Expand Down Expand Up @@ -239,5 +240,89 @@ BOOST_AUTO_TEST_CASE( testFileIntersectionTest )
}
}

BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(testSolidSolidInxWithMultiSolidResult)
{
std::unique_ptr<SFCGAL::Geometry> poly1 = SFCGAL::io::readWkt("POLYGON Z((0 0,1 0,1 1,0 1,0 0))");
std::unique_ptr<SFCGAL::Geometry> solid1 = SFCGAL::algorithm::extrude(*poly1, 0.0, 0.0, 1.0);

std::unique_ptr<SFCGAL::Geometry> poly2 = SFCGAL::io::readWkt("POLYGON Z((0.5 0, 1.5 0, 1.5 1, 0.5 1, 1.1 0.5, 0.5 0))");
std::unique_ptr<SFCGAL::Geometry> solid2 = SFCGAL::algorithm::extrude(*poly2, 0.0, 0.0, 1.0);

std::unique_ptr<SFCGAL::Geometry> inx = SFCGAL::algorithm::intersection3D(*solid1, *solid2);

const std::string expected
= "MULTISOLID Z("
"(("
"((0.50000 0.00000 1.00000,0.50000 0.00000 0.00000,1.00000 0.00000 0.00000,1.00000 0.00000 1.00000,0.50000 0.00000 1.00000)),"
"((1.00000 0.00000 0.00000,0.50000 0.00000 0.00000,1.00000 0.41667 0.00000,1.00000 0.00000 0.00000)),"
"((1.00000 0.41667 0.00000,0.50000 0.00000 0.00000,0.50000 0.00000 1.00000,1.00000 0.41667 1.00000,1.00000 0.41667 0.00000)),"
"((1.00000 0.41667 1.00000,0.50000 0.00000 1.00000,1.00000 0.00000 1.00000,1.00000 0.41667 1.00000)),"
"((1.00000 0.00000 1.00000,1.00000 0.00000 0.00000,1.00000 0.41667 0.00000,1.00000 0.41667 1.00000,1.00000 0.00000 1.00000))"
")),"
"(("
"((1.00000 0.58333 0.00000,0.50000 1.00000 0.00000,1.00000 1.00000 0.00000,1.00000 0.58333 0.00000)),"
"((1.00000 1.00000 0.00000,0.50000 1.00000 0.00000,0.50000 1.00000 1.00000,1.00000 1.00000 1.00000,1.00000 1.00000 0.00000)),"
"((0.50000 1.00000 1.00000,0.50000 1.00000 0.00000,1.00000 0.58333 0.00000,1.00000 0.58333 1.00000,0.50000 1.00000 1.00000)),"
"((1.00000 0.58333 1.00000,1.00000 0.58333 0.00000,1.00000 1.00000 0.00000,1.00000 1.00000 1.00000,1.00000 0.58333 1.00000)),"
"((1.00000 1.00000 1.00000,0.50000 1.00000 1.00000,1.00000 0.58333 1.00000,1.00000 1.00000 1.00000))"
"))"
")";

#if 0
std::cout << "TEST testSolidSolidInxWithMultiSolidResult: actual\n"
<< actual
<< "\nexpected:\n"
<< expected
<< std::endl;
#endif

BOOST_ASSERT(inx->geometryType() == SFCGAL::TYPE_MULTISOLID);
BOOST_CHECK_EQUAL(inx->as<SFCGAL::GeometryCollection>().numGeometries(), 2);
}

BOOST_AUTO_TEST_CASE(testSolidSolidInxWithMultiSolidResult2)
{
std::unique_ptr<SFCGAL::Geometry> poly1 = SFCGAL::io::readWkt("POLYGON((0 0,1 0,1 1,0 1,0 0))");
std::unique_ptr<SFCGAL::Geometry> solid1 = SFCGAL::algorithm::extrude(*poly1, 0.0, 0.0, 1.0);

std::unique_ptr<SFCGAL::Geometry> poly2
= SFCGAL::io::readWkt("POLYGON((-1 0.2,1.8 0.2,1.8 0.4,-0.8 0.4,-0.8 0.6,1.8 0.6,1.8 0.8,-1 0.8,-1 0.2))");

std::unique_ptr<SFCGAL::Geometry> solid2 = SFCGAL::algorithm::extrude(*poly2, 0.0, 0.0, 1.0);

std::unique_ptr<SFCGAL::Geometry> inx = SFCGAL::algorithm::intersection3D(*solid1, *solid2);

const std::string expected
= "MULTISOLID Z("
"(("
"((0.00000 0.20000 1.00000,0.00000 0.20000 0.00000,1.00000 0.20000 0.00000,1.00000 0.20000 1.00000,0.00000 0.20000 1.00000)),"
"((1.00000 0.20000 0.00000,0.00000 0.20000 0.00000,0.00000 0.40000 0.00000,1.00000 0.40000 0.00000,1.00000 0.20000 0.00000)),"
"((0.00000 0.40000 0.00000,0.00000 0.20000 0.00000,0.00000 0.20000 1.00000,0.00000 0.40000 1.00000,0.00000 0.40000 0.00000)),"
"((0.00000 0.40000 1.00000,0.00000 0.20000 1.00000,1.00000 0.20000 1.00000,1.00000 0.40000 1.00000,0.00000 0.40000 1.00000)),"
"((1.00000 0.20000 1.00000,1.00000 0.20000 0.00000,1.00000 0.40000 0.00000,1.00000 0.40000 1.00000,1.00000 0.20000 1.00000)),"
"((1.00000 0.40000 0.00000,0.00000 0.40000 0.00000,0.00000 0.40000 1.00000,1.00000 0.40000 1.00000,1.00000 0.40000 0.00000))"
")),"
"(("
"((0.00000 0.80000 0.00000,0.00000 0.60000 0.00000,0.00000 0.60000 1.00000,0.00000 0.80000 1.00000,0.00000 0.80000 0.00000)),"
"((0.00000 0.60000 1.00000,0.00000 0.60000 0.00000,1.00000 0.60000 0.00000,1.00000 0.60000 1.00000,0.00000 0.60000 1.00000)),"
"((1.00000 0.60000 0.00000,0.00000 0.60000 0.00000,0.00000 0.80000 0.00000,1.00000 0.80000 0.00000,1.00000 0.60000 0.00000)),"
"((1.00000 0.80000 0.00000,0.00000 0.80000 0.00000,0.00000 0.80000 1.00000,1.00000 0.80000 1.00000,1.00000 0.80000 0.00000)),"
"((0.00000 0.80000 1.00000,0.00000 0.60000 1.00000,1.00000 0.60000 1.00000,1.00000 0.80000 1.00000,0.00000 0.80000 1.00000)),"
"((1.00000 0.60000 1.00000,1.00000 0.60000 0.00000,1.00000 0.80000 0.00000,1.00000 0.80000 1.00000,1.00000 0.60000 1.00000))"
"))"
")";

#if 0
const std::string actual = inx->asText(5);
std::cout << "TEST testSolidSolidInxWithMultiSolidResult2: actual\n"
<< actual
<< "\nexpected:\n"
<< expected
<< std::endl;
#endif

BOOST_ASSERT(inx->geometryType() == SFCGAL::TYPE_MULTISOLID);
BOOST_CHECK_EQUAL(inx->as<SFCGAL::GeometryCollection>().numGeometries(), 2);
}

BOOST_AUTO_TEST_SUITE_END()