Skip to content

Commit

Permalink
Merge pull request #7 from 3DGI/develop-api
Browse files Browse the repository at this point in the history
C++ API
  • Loading branch information
Ylannl authored Jun 2, 2024
2 parents 94547c6 + bce7bc4 commit 0d52eac
Show file tree
Hide file tree
Showing 84 changed files with 1,544 additions and 706 deletions.
1 change: 1 addition & 0 deletions apps/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ include_directories("${CMAKE_CURRENT_SOURCE_DIR}/external")

add_subdirectory(crop)
add_subdirectory(reconstruct)
add_subdirectory(reconstruct_api)

if(WIN32)
install (DIRECTORY ${CMAKE_BINARY_DIR}/vcpkg_installed/${VCPKG_TARGET_TRIPLET}/share/proj
Expand Down
50 changes: 25 additions & 25 deletions apps/crop/crop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,14 +259,14 @@ int main(int argc, const char * argv[]) {
return EXIT_FAILURE;
}

auto pj = roofer::createProjHelper();
auto VectorReader = roofer::createVectorReaderOGR(*pj);
auto VectorWriter = roofer::createVectorWriterOGR(*pj);
auto pj = roofer::misc::createProjHelper();
auto VectorReader = roofer::io::createVectorReaderOGR(*pj);
auto VectorWriter = roofer::io::createVectorWriterOGR(*pj);
VectorWriter->srs = output_crs;
auto RasterWriter = roofer::createRasterWriterGDAL(*pj);
auto PointCloudCropper = roofer::createPointCloudCropper(*pj);
auto VectorOps = roofer::createVector2DOpsGEOS();
auto LASWriter = roofer::createLASWriter(*pj);
auto RasterWriter = roofer::io::createRasterWriterGDAL(*pj);
auto PointCloudCropper = roofer::io::createPointCloudCropper(*pj);
auto VectorOps = roofer::misc::createVector2DOpsGEOS();
auto LASWriter = roofer::io::createLASWriter(*pj);

VectorReader->open(path_footprint);
logger.info("Reading footprints from {}", path_footprint);
Expand Down Expand Up @@ -333,14 +333,14 @@ int main(int argc, const char * argv[]) {
// auto& r_nodata = attributes.insert_vec<float>("r_nodata_"+ipc.name);
roofer::arr2f nodata_c;
for(unsigned i=0; i<N_fp; ++i) {
roofer::RasterisePointcloud(
roofer::misc::RasterisePointcloud(
ipc.building_clouds[i],
footprints[i],
ipc.building_rasters[i],
cellsize
);
ipc.nodata_fractions[i] = roofer::computeNoDataFraction(ipc.building_rasters[i]);
ipc.pt_densities[i] = roofer::computePointDensity(ipc.building_rasters[i]);
ipc.nodata_fractions[i] = roofer::misc::computeNoDataFraction(ipc.building_rasters[i]);
ipc.pt_densities[i] = roofer::misc::computePointDensity(ipc.building_rasters[i]);

auto target_density = max_point_density;
bool low_lod = *(*low_lod_vec)[i];
Expand All @@ -352,7 +352,7 @@ int main(int argc, const char * argv[]) {
low_lod);
}

gridthinPointcloud(
roofer::misc::gridthinPointcloud(
ipc.building_clouds[i],
ipc.building_rasters[i]["cnt"],
target_density
Expand All @@ -361,7 +361,7 @@ int main(int argc, const char * argv[]) {
if (low_lod) {
ipc.nodata_radii[i] = 0;
} else {
roofer::compute_nodata_circle(
roofer::misc::compute_nodata_circle(
ipc.building_clouds[i],
footprints[i],
&ipc.nodata_radii[i],
Expand Down Expand Up @@ -393,14 +393,14 @@ int main(int argc, const char * argv[]) {
}
}

roofer::selectPointCloudConfig select_pc_cfg;
roofer::misc::selectPointCloudConfig select_pc_cfg;
if (input_pointclouds.size() > 1){
auto& is_mutated = attributes.insert_vec<bool>(
"is_mutated_"+input_pointclouds[0].name+"_"+input_pointclouds[1].name
);
is_mutated.reserve(N_fp);
for (unsigned i=0; i<N_fp; ++i) {
is_mutated[i] = roofer::isMutated(
is_mutated[i] = roofer::misc::isMutated(
input_pointclouds[0].building_rasters[i],
input_pointclouds[1].building_rasters[i],
select_pc_cfg.threshold_mutation_fraction,
Expand All @@ -427,13 +427,13 @@ int main(int argc, const char * argv[]) {
}
// spdlog::debug("bid={}", bid);

std::vector<roofer::CandidatePointCloud> candidates;
std::vector<roofer::misc::CandidatePointCloud> candidates;
candidates.reserve(input_pointclouds.size());
std::vector<roofer::CandidatePointCloud> candidates_just_for_data;
std::vector<roofer::misc::CandidatePointCloud> candidates_just_for_data;
{
int j=0;
for (auto& ipc : input_pointclouds) {
auto cpc = roofer::CandidatePointCloud {
auto cpc = roofer::misc::CandidatePointCloud {
ipc.nodata_radii[i],
ipc.nodata_fractions[i],
ipc.building_rasters[i],
Expand All @@ -453,8 +453,8 @@ int main(int argc, const char * argv[]) {
jsonl_paths.insert({"", roofer::vec1s{}});
}

roofer::PointCloudSelectResult sresult = roofer::selectPointCloud(candidates, select_pc_cfg);
const roofer::CandidatePointCloud* selected = sresult.selected_pointcloud;
roofer::misc::PointCloudSelectResult sresult = roofer::misc::selectPointCloud(candidates, select_pc_cfg);
const roofer::misc::CandidatePointCloud* selected = sresult.selected_pointcloud;

// this is a sanity check and should never happen
if (!selected) {
Expand All @@ -467,7 +467,7 @@ int main(int argc, const char * argv[]) {
if (yoc != -1 && yoc > selected->date) {
// force selection of latest pointcloud
selected = getLatestPointCloud(candidates);
sresult.explanation = roofer::PointCloudSelectExplanation::_LATEST;
sresult.explanation = roofer::misc::PointCloudSelectExplanation::_LATEST;
// overrule if there was a more recent pointcloud with select_only_for_date = true
if (candidates_just_for_data.size()) {
if ( candidates_just_for_data[0].date > selected->date ) {
Expand All @@ -477,15 +477,15 @@ int main(int argc, const char * argv[]) {
}
}

if (sresult.explanation == roofer::PointCloudSelectExplanation::PREFERRED_AND_LATEST )
if (sresult.explanation == roofer::misc::PointCloudSelectExplanation::PREFERRED_AND_LATEST )
pc_select.push_back("PREFERRED_AND_LATEST");
else if (sresult.explanation == roofer::PointCloudSelectExplanation::PREFERRED_NOT_LATEST )
else if (sresult.explanation == roofer::misc::PointCloudSelectExplanation::PREFERRED_NOT_LATEST )
pc_select.push_back("PREFERRED_NOT_LATEST");
else if (sresult.explanation == roofer::PointCloudSelectExplanation::LATEST_WITH_MUTATION )
else if (sresult.explanation == roofer::misc::PointCloudSelectExplanation::LATEST_WITH_MUTATION )
pc_select.push_back("LATEST_WITH_MUTATION");
else if (sresult.explanation == roofer::PointCloudSelectExplanation::_HIGHEST_YET_INSUFFICIENT_COVERAGE )
else if (sresult.explanation == roofer::misc::PointCloudSelectExplanation::_HIGHEST_YET_INSUFFICIENT_COVERAGE )
pc_select.push_back("_HIGHEST_YET_INSUFFICIENT_COVERAGE");
else if (sresult.explanation == roofer::PointCloudSelectExplanation::_LATEST ) {
else if (sresult.explanation == roofer::misc::PointCloudSelectExplanation::_LATEST ) {
pc_select.push_back("_LATEST");
// // clear pc
// ipc[selected->index].building_clouds[i].clear();
Expand Down
56 changes: 28 additions & 28 deletions apps/reconstruct/reconstruct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ namespace fs = std::filesystem;
enum LOD {LOD12=12, LOD13=13, LOD22=22};

std::unordered_map<int, roofer::Mesh> extrude(
Arrangement_2 arrangement,
roofer::Arrangement_2 arrangement,
float floor_elevation,
#ifdef RF_USE_VAL3DITY
std::vector<std::optional<std::string> >& attr_val3dity,
#endif
std::vector<std::optional<float> >& attr_rmse,
roofer::detection::SegmentRasteriserInterface* SegmentRasteriser,
roofer::detection::PlaneDetectorInterface* PlaneDetector,
roofer::reconstruction::SegmentRasteriserInterface* SegmentRasteriser,
roofer::reconstruction::PlaneDetectorInterface* PlaneDetector,
LOD lod
) {
bool dissolve_step_edges = false;
Expand All @@ -98,7 +98,7 @@ std::unordered_map<int, roofer::Mesh> extrude(

auto &logger = roofer::logger::Logger::get_logger();

auto ArrangementDissolver = roofer::detection::createArrangementDissolver();
auto ArrangementDissolver = roofer::reconstruction::createArrangementDissolver();
ArrangementDissolver->compute(
arrangement,
SegmentRasteriser->heightfield,
Expand All @@ -110,18 +110,18 @@ std::unordered_map<int, roofer::Mesh> extrude(
logger.info("Completed ArrangementDissolver");
logger.info("Roof partition has {} faces", arrangement.number_of_faces());
#ifdef RF_USE_RERUN
rec.log(worldname+"ArrangementDissolver", rerun::LineStrips3D( roofer::detection::arr2polygons(arrangement) ));
rec.log(worldname+"ArrangementDissolver", rerun::LineStrips3D( roofer::reconstruction::arr2polygons(arrangement) ));
#endif
auto ArrangementSnapper = roofer::detection::createArrangementSnapper();
auto ArrangementSnapper = roofer::reconstruction::createArrangementSnapper();
ArrangementSnapper->compute(
arrangement
);
logger.info("Completed ArrangementSnapper");
#ifdef RF_USE_RERUN
// rec.log(worldname+"ArrangementSnapper", rerun::LineStrips3D( roofer::detection::arr2polygons(arrangement) ));
// rec.log(worldname+"ArrangementSnapper", rerun::LineStrips3D( roofer::reconstruction::arr2polygons(arrangement) ));
#endif

auto ArrangementExtruder = roofer::detection::createArrangementExtruder();
auto ArrangementExtruder = roofer::reconstruction::createArrangementExtruder();
ArrangementExtruder->compute(
arrangement,
floor_elevation,
Expand All @@ -134,7 +134,7 @@ std::unordered_map<int, roofer::Mesh> extrude(
rec.log(worldname+"ArrangementExtruder", rerun::LineStrips3D(ArrangementExtruder->faces).with_class_ids(ArrangementExtruder->labels));
#endif

auto MeshTriangulator = roofer::detection::createMeshTriangulatorLegacy();
auto MeshTriangulator = roofer::reconstruction::createMeshTriangulatorLegacy();
MeshTriangulator->compute(
ArrangementExtruder->multisolid
);
Expand All @@ -143,7 +143,7 @@ std::unordered_map<int, roofer::Mesh> extrude(
rec.log(worldname+"MeshTriangulator", rerun::Mesh3D(MeshTriangulator->triangles).with_vertex_normals(MeshTriangulator->normals).with_class_ids(MeshTriangulator->ring_ids));
#endif

auto PC2MeshDistCalculator = roofer::detection::createPC2MeshDistCalculator();
auto PC2MeshDistCalculator = roofer::misc::createPC2MeshDistCalculator();
PC2MeshDistCalculator->compute(
PlaneDetector->pts_per_roofplane,
MeshTriangulator->multitrianglecol,
Expand All @@ -156,7 +156,7 @@ std::unordered_map<int, roofer::Mesh> extrude(
#endif

#ifdef RF_USE_VAL3DITY
auto Val3dator = roofer::detection::createVal3dator();
auto Val3dator = roofer::reconstruction::createVal3dator();
Val3dator->compute(
ArrangementExtruder->multisolid
);
Expand Down Expand Up @@ -327,7 +327,7 @@ int main(int argc, const char * argv[]) {
}

// Create Writer. TODO: check if we can write to output file prior to doing reconstruction?
auto pj = roofer::createProjHelper();
auto pj = roofer::misc::createProjHelper();
auto CityJsonWriter = roofer::io::createCityJsonWriter(*pj);
CityJsonWriter->CRS_ = crs_output;
CityJsonWriter->identifier_attribute = building_bid_attribute;
Expand All @@ -342,8 +342,8 @@ int main(int argc, const char * argv[]) {
pj->set_process_crs(crs_process.c_str());
roofer::arr3d offset = {offset_x, offset_y, offset_z};
pj->set_data_offset(offset);
auto PointReader = roofer::createPointCloudReaderLASlib(*pj);
auto VectorReader = roofer::createVectorReaderOGR(*pj);
auto PointReader = roofer::io::createPointCloudReaderLASlib(*pj);
auto VectorReader = roofer::io::createVectorReaderOGR(*pj);

VectorReader->open(path_footprint);
std::vector<roofer::LinearRing> footprints;
Expand Down Expand Up @@ -386,7 +386,7 @@ int main(int argc, const char * argv[]) {
rec.log("world/raw_points", rerun::Points3D(points).with_class_ids(classification));
#endif

auto PlaneDetector = roofer::detection::createPlaneDetector();
auto PlaneDetector = roofer::reconstruction::createPlaneDetector();
PlaneDetector->detect(points_roof);
logger.info("Completed PlaneDetector (roof), found {} roofplanes", PlaneDetector->pts_per_roofplane.size());

Expand Down Expand Up @@ -416,7 +416,7 @@ int main(int argc, const char * argv[]) {
);
}

auto PlaneDetector_ground = roofer::detection::createPlaneDetector();
auto PlaneDetector_ground = roofer::reconstruction::createPlaneDetector();
PlaneDetector_ground->detect(points_ground);
logger.info("Completed PlaneDetector (ground), found {} groundplanes", PlaneDetector_ground->pts_per_roofplane.size());

Expand All @@ -441,7 +441,7 @@ int main(int argc, const char * argv[]) {
attr_skip.push_back(skip);

if (skip) {
auto SimplePolygonExtruder = roofer::detection::createSimplePolygonExtruder();
auto SimplePolygonExtruder = roofer::reconstruction::createSimplePolygonExtruder();
SimplePolygonExtruder->compute(
footprints[fp_i],
floor_elevation,
Expand All @@ -459,42 +459,42 @@ int main(int argc, const char * argv[]) {
);
logger.info("Completed CityJsonWriter to {}", path_output_jsonl);
} else {
auto AlphaShaper = roofer::detection::createAlphaShaper();
auto AlphaShaper = roofer::reconstruction::createAlphaShaper();
AlphaShaper->compute(PlaneDetector->pts_per_roofplane);
logger.info("Completed AlphaShaper (roof), found {} rings, {} labels", AlphaShaper->alpha_rings.size(), AlphaShaper->roofplane_ids.size());
#ifdef RF_USE_RERUN
rec.log("world/alpha_rings_roof", rerun::LineStrips3D(AlphaShaper->alpha_rings).with_class_ids(AlphaShaper->roofplane_ids));
#endif

auto AlphaShaper_ground = roofer::detection::createAlphaShaper();
auto AlphaShaper_ground = roofer::reconstruction::createAlphaShaper();
AlphaShaper_ground->compute(PlaneDetector_ground->pts_per_roofplane);
logger.info("Completed AlphaShaper (ground), found {} rings, {} labels", AlphaShaper_ground->alpha_rings.size(), AlphaShaper_ground->roofplane_ids.size());
#ifdef RF_USE_RERUN
rec.log("world/alpha_rings_ground", rerun::LineStrips3D(AlphaShaper_ground->alpha_rings).with_class_ids(AlphaShaper_ground->roofplane_ids));
#endif

auto LineDetector = roofer::detection::createLineDetector();
auto LineDetector = roofer::reconstruction::createLineDetector();
LineDetector->detect(AlphaShaper->alpha_rings, AlphaShaper->roofplane_ids, PlaneDetector->pts_per_roofplane);
logger.info("Completed LineDetector");
#ifdef RF_USE_RERUN
rec.log("world/boundary_lines", rerun::LineStrips3D(LineDetector->edge_segments));
#endif

auto PlaneIntersector = roofer::detection::createPlaneIntersector();
auto PlaneIntersector = roofer::reconstruction::createPlaneIntersector();
PlaneIntersector->compute(PlaneDetector->pts_per_roofplane, PlaneDetector->plane_adjacencies);
logger.info("Completed PlaneIntersector");
#ifdef RF_USE_RERUN
rec.log("world/intersection_lines", rerun::LineStrips3D(PlaneIntersector->segments));
#endif

auto LineRegulariser = roofer::detection::createLineRegulariser();
auto LineRegulariser = roofer::reconstruction::createLineRegulariser();
LineRegulariser->compute(LineDetector->edge_segments, PlaneIntersector->segments);
logger.info("Completed LineRegulariser");
#ifdef RF_USE_RERUN
rec.log("world/regularised_lines", rerun::LineStrips3D(LineRegulariser->regularised_edges));
#endif

auto SegmentRasteriser = roofer::detection::createSegmentRasteriser();
auto SegmentRasteriser = roofer::reconstruction::createSegmentRasteriser();
SegmentRasteriser->compute(
AlphaShaper->alpha_triangles,
AlphaShaper_ground->alpha_triangles
Expand All @@ -513,8 +513,8 @@ int main(int argc, const char * argv[]) {
);
#endif

Arrangement_2 arrangement;
auto ArrangementBuilder = roofer::detection::createArrangementBuilder();
roofer::Arrangement_2 arrangement;
auto ArrangementBuilder = roofer::reconstruction::createArrangementBuilder();
ArrangementBuilder->compute(
arrangement,
footprints[fp_i],
Expand All @@ -523,18 +523,18 @@ int main(int argc, const char * argv[]) {
logger.info("Completed ArrangementBuilder");
logger.info("Roof partition has {} faces", arrangement.number_of_faces());
#ifdef RF_USE_RERUN
rec.log("world/initial_partition", rerun::LineStrips3D( roofer::detection::arr2polygons(arrangement) ));
rec.log("world/initial_partition", rerun::LineStrips3D( roofer::reconstruction::arr2polygons(arrangement) ));
#endif

auto ArrangementOptimiser = roofer::detection::createArrangementOptimiser();
auto ArrangementOptimiser = roofer::reconstruction::createArrangementOptimiser();
ArrangementOptimiser->compute(
arrangement,
SegmentRasteriser->heightfield,
PlaneDetector->pts_per_roofplane,
PlaneDetector_ground->pts_per_roofplane
);
logger.info("Completed ArrangementOptimiser");
// rec.log("world/optimised_partition", rerun::LineStrips3D( roofer::detection::arr2polygons(arrangement) ));
// rec.log("world/optimised_partition", rerun::LineStrips3D( roofer::reconstruction::arr2polygons(arrangement) ));

// LoDs
// attributes to be filled during reconstruction
Expand Down
16 changes: 16 additions & 0 deletions apps/reconstruct_api/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
set(APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/reconstruct_api.cpp")

add_executable("reconstruct_api" ${APP_SOURCES})
set_target_properties("reconstruct_api" PROPERTIES CXX_STANDARD 20)

set(RECONSTRUCT_LINK_LIBS
roofer-extra
cmake_git_version_tracking
)
if(RF_USE_RERUN)
list(APPEND RECONSTRUCT_LINK_LIBS rerun_sdk)
endif()

target_link_libraries(
"reconstruct_api"
PRIVATE ${RECONSTRUCT_LINK_LIBS})
Loading

0 comments on commit 0d52eac

Please sign in to comment.