272 std::vector<int> toDelete;
274 for (
int i = mesh.
indices.size() - 3; i >= 0; i -= 3 ) {
284 for (
int j = i - 3; j >= 0; j -= 3 ) {
294 if ( n.
x > 0.0 && n2.
x < 0.0 ) {
312 toDelete.push_back( i );
315 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i], mesh.indices[j], mesh.indices[i + 2] } );
316 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i + 2], mesh.indices[j], mesh.indices[i + 1] } );
318 std::cout <<
"t=" << t << std::endl;
319 std::cout <<
"added new triangles" << std::endl;
326 toDelete.push_back( i );
329 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i], mesh.indices[j + 1], mesh.indices[i + 2] } );
330 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i + 2], mesh.indices[j + 1], mesh.indices[i + 1] } );
332 std::cout <<
"added new triangles" << std::endl;
339 toDelete.push_back( i );
342 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i], mesh.indices[j + 2], mesh.indices[i + 2] } );
343 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i + 2], mesh.indices[j + 2], mesh.indices[i + 1] } );
345 std::cout <<
"added new triangles" << std::endl;
352 toDelete.push_back( i );
355 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i], mesh.indices[i + 1], mesh.indices[j] } );
356 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i], mesh.indices[j], mesh.indices[i + 2] } );
358 std::cout <<
"added new triangles" << std::endl;
365 toDelete.push_back( i );
368 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i], mesh.indices[i + 1], mesh.indices[j + 1] } );
369 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i], mesh.indices[j + 1], mesh.indices[i + 2] } );
371 std::cout <<
"added new triangles" << std::endl;
378 toDelete.push_back( i );
381 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i], mesh.indices[i + 1], mesh.indices[j + 2] } );
382 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i], mesh.indices[j + 2], mesh.indices[i + 2] } );
384 std::cout <<
"added new triangles" << std::endl;
391 toDelete.push_back( i );
394 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i], mesh.indices[i + 1], mesh.indices[j] } );
395 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i + 2], mesh.indices[j], mesh.indices[i + 1] } );
397 std::cout <<
"added new triangles" << std::endl;
404 toDelete.push_back( i );
407 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i], mesh.indices[i + 1], mesh.indices[j + 1] } );
408 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i + 2], mesh.indices[j + 1], mesh.indices[i + 1] } );
410 std::cout <<
"added new triangles" << std::endl;
417 toDelete.push_back( i );
420 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i], mesh.indices[i + 1], mesh.indices[j + 2] } );
421 mesh.
indices.insert( mesh.
indices.end(), { mesh.indices[i + 2], mesh.indices[j + 2], mesh.indices[i + 1] } );
423 std::cout <<
"added new triangles" << std::endl;
1169std::vector<Polygon>
csgfixtjunc(
const std::vector<Polygon> &originalpolygons )
1176 struct IndexedVertex {
1182 const IndexedVertex *vertex0;
1183 const IndexedVertex *vertex1;
1187 std::vector<IndexedVertex> uvertices;
1189 struct IndexPolygon {
1190 std::vector<size_t> vertexindex;
1192 std::vector<IndexPolygon> polygons;
1193 for (
const auto &originalpoly : originalpolygons ) {
1195 for (
const auto &v : originalpoly.vertices ) {
1196 auto pos = std::find_if( uvertices.begin(), uvertices.end(), [v](
const IndexedVertex &a ) { return a.vertex == v; } );
1197 if ( pos != uvertices.end() ) {
1198 size_t index = pos - uvertices.begin();
1199 ipoly.vertexindex.push_back( index );
1201 size_t index = uvertices.size();
1202 ipoly.vertexindex.push_back( index );
1203 uvertices.push_back( { v, index } );
1206 polygons.push_back( ipoly );
1212 std::map<SideTag, std::vector<Side> > sidemap = {};
1214 for (
int polygonindex = 0; polygonindex < (int)polygons.size(); polygonindex++ ) {
1215 auto &polygon = polygons[polygonindex];
1216 size_t numvertices = polygon.vertexindex.size();
1217 if ( numvertices < 3 ) {
1221 IndexedVertex *vertex = &uvertices[polygon.vertexindex[0]];
1222 Tag vertextag = vertex->index;
1223 for (
size_t vertexindex = 0; vertexindex < numvertices; vertexindex++ ) {
1224 size_t nextvertexindex = vertexindex + 1;
1225 if ( nextvertexindex == numvertices ) {
1226 nextvertexindex = 0;
1229 IndexedVertex *nextvertex = &uvertices[polygon.vertexindex[nextvertexindex]];
1230 Tag nextvertextag = nextvertex->index;
1231 auto sidetag = std::make_pair( vertextag, nextvertextag );
1232 auto reversesidetag = std::make_pair( nextvertextag, vertextag );
1234 auto sidemappos = sidemap.find( reversesidetag );
1235 if ( sidemappos != sidemap.end() ) {
1238 auto &ar = sidemappos->second;
1240 if ( ar.size() == 0 ) {
1241 sidemap.erase( sidemappos );
1244 sidemap[sidetag].push_back( { vertex, nextvertex, polygonindex } );
1257 vertex = nextvertex;
1258 vertextag = nextvertextag;
1266 std::map<Tag, std::vector<SideTag> > vertextag2sidestart;
1268 std::map<Tag, std::vector<SideTag> > vertextag2sideend;
1269 std::deque<SideTag> sidestocheck;
1271 bool sidemapisempty =
true;
1272 for (
const auto &iter : sidemap ) {
1273 const SideTag &sidetag = iter.first;
1274 const std::vector<Side> &sideobjs = iter.second;
1276 sidemapisempty =
false;
1277 sidestocheck.push_back( sidetag );
1279 for (
auto &sideobj : sideobjs ) {
1280 Tag starttag = sideobj.vertex0->index;
1281 Tag endtag = sideobj.vertex1->index;
1282 vertextag2sidestart[starttag].push_back( sidetag );
1288 vertextag2sideend[endtag].push_back( sidetag );
1299 if ( !sidemapisempty ) {
1301 auto deleteSide = [&sidemap, &vertextag2sidestart, &vertextag2sideend](
const IndexedVertex &vertex0,
const IndexedVertex &vertex1,
int polygonindex ) {
1302 auto starttag = vertex0.index;
1303 auto endtag = vertex1.index;
1304 auto sidetag = std::make_pair( starttag, endtag );
1306 assert(
contains( sidemap, sidetag ) &&
"logic error" );
1310 auto sideobjs = sidemap.at( sidetag );
1311 for (
size_t i = 0; i < sideobjs.size(); i++ ) {
1312 auto &sideobj = sideobjs[i];
1313 if ( sideobj.vertex0->index != vertex0.index )
1315 if ( sideobj.vertex1->index != vertex1.index )
1318 if ( sideobj.polygonindex != polygonindex )
1324 assert( idx >= 0 &&
"logic error" );
1325 sideobjs.erase( sideobjs.begin() + idx );
1326 if ( sideobjs.size() == 0 ) {
1327 remove( sidemap, sidetag );
1329 auto siter =
find( vertextag2sidestart[starttag], sidetag );
1330 assert( siter != vertextag2sidestart[starttag].end() &&
"logic error" );
1331 vertextag2sidestart[starttag].erase( siter );
1332 if ( vertextag2sidestart[starttag].size() == 0 ) {
1333 remove( vertextag2sidestart, starttag );
1335 auto eiter =
find( vertextag2sideend[endtag], sidetag );
1336 assert( eiter != vertextag2sideend[endtag].end() &&
"logic error" );
1337 vertextag2sideend[endtag].erase( eiter );
1338 if ( vertextag2sideend[endtag].size() == 0 ) {
1339 remove( vertextag2sideend, endtag );
1343 auto addSide = [&sidemap, &deleteSide, &vertextag2sidestart, &vertextag2sideend](
const IndexedVertex &vertex0,
const IndexedVertex &vertex1,
int polygonindex,
SideTag &addedtag ) ->
bool {
1344 auto starttag = vertex0.index;
1345 auto endtag = vertex1.index;
1346 assert( starttag != endtag &&
"logic error" );
1347 auto newsidetag = std::make_pair( starttag, endtag );
1348 auto reversesidetag = std::make_pair( endtag, starttag );
1349 if (
contains( sidemap, reversesidetag ) ) {
1357 Side newsideobj{ &vertex0, &vertex1, polygonindex };
1358 sidemap[newsidetag].push_back( newsideobj );
1359 vertextag2sidestart[starttag].push_back( newsidetag );
1360 vertextag2sideend[endtag].push_back( newsidetag );
1361 addedtag = newsidetag;
1367 bool sidemapisempty2 =
true;
1368 for (
auto &iter : sidemap ) {
1369 const auto &sidetag = iter.first;
1370 sidemapisempty2 =
false;
1371 sidestocheck.push_back( sidetag );
1373 if ( sidemapisempty2 ) {
1376 bool donesomething =
false;
1377 while (
false == sidestocheck.empty() ) {
1379 SideTag sidetagtocheck = sidestocheck.front();
1380 sidestocheck.pop_front();
1387 bool donewithside =
true;
1388 if (
contains( sidemap, sidetagtocheck ) ) {
1389 auto &sideobjs = sidemap[sidetagtocheck];
1390 assert( sideobjs.size() &&
"didn't expect an empty set of sides" );
1392 Side &side = sideobjs[0];
1393 for (
int directionindex = 0; directionindex < 2; directionindex++ ) {
1394 auto startvertex = ( directionindex == 0 ) ? side.vertex0 : side.vertex1;
1395 auto endvertex = ( directionindex == 0 ) ? side.vertex1 : side.vertex0;
1396 auto startvertextag = startvertex->index;
1397 auto endvertextag = endvertex->index;
1398 std::vector<SideTag> matchingsides;
1399 if ( directionindex == 0 ) {
1400 if (
contains( vertextag2sideend, startvertextag ) ) {
1401 matchingsides = vertextag2sideend[startvertextag];
1404 if (
contains( vertextag2sidestart, startvertextag ) ) {
1405 matchingsides = vertextag2sidestart[startvertextag];
1408 for (
const auto &matchingsidetag : matchingsides ) {
1410 auto matchingside = sidemap[matchingsidetag][0];
1411 auto matchingsidestartvertex = ( directionindex == 0 ) ? matchingside.vertex0 : matchingside.vertex1;
1412 auto matchingsidestartvertextag = matchingsidestartvertex->index;
1413#if !defined( NDEBUG )
1414 auto matchingsideendvertex = ( directionindex == 0 ) ? matchingside.vertex1 : matchingside.vertex0;
1415 auto matchingsideendvertextag = matchingsideendvertex->index;
1416 assert( matchingsideendvertextag == startvertextag &&
"logic error" );
1418 if ( matchingsidestartvertextag == endvertextag ) {
1422 donewithside =
false;
1424 donesomething =
true;
1427 auto startpos = startvertex->vertex.pos;
1428 auto endpos = endvertex->vertex.pos;
1429 auto checkpos = matchingsidestartvertex->vertex.pos;
1430 auto direction = checkpos - startpos;
1432 double t =
dot( ( endpos - startpos ), direction ) /
dot( direction, direction );
1433 if ( ( t > 0.0 ) && ( t < 1.0 ) ) {
1434 auto closestpoint = startpos + direction * t;
1435 auto distancesquared =
lengthsquared( closestpoint - endpos );
1436 if ( distancesquared < 1e-10 ) {
1438 auto polygonindex = matchingside.polygonindex;
1439 auto polygon = polygons[polygonindex];
1441 auto insertionvertextag = matchingside.vertex1->index;
1442 int insertionvertextagindex = -1;
1443 for (
int i = 0; i < (int)polygon.vertexindex.size(); i++ ) {
1444 if ( polygon.vertexindex[i] == insertionvertextag ) {
1445 insertionvertextagindex = i;
1449 assert( insertionvertextagindex >= 0 &&
"logic error" );
1451 auto newvertices = polygon.vertexindex;
1452 newvertices.insert( newvertices.begin() + insertionvertextagindex, endvertex->index );
1453 polygons[polygonindex].vertexindex = newvertices;
1457 deleteSide( *matchingside.vertex0, *matchingside.vertex1, polygonindex );
1458 SideTag newsidetag1, newsidetag2;
1459 if ( addSide( *matchingside.vertex0, *endvertex, polygonindex, newsidetag1 ) ) {
1460 sidestocheck.push_back( newsidetag1 );
1462 if ( addSide( *endvertex, *matchingside.vertex1, polygonindex, newsidetag2 ) ) {
1463 sidestocheck.push_back( newsidetag2 );
1465 donewithside =
false;
1467 donesomething =
true;
1475 if ( donewithside ) {
1479 if ( !donesomething ) {
1485 std::vector<Polygon> outpolys;
1486 for (
const auto &indexedpoly : polygons ) {
1488 for (
auto i : indexedpoly.vertexindex ) {
1489 p.
vertices.push_back( uvertices[i].vertex );
1491 assert( p.
vertices.size() > 2 &&
"logic error" );
1493 outpolys.push_back( p );