Skip to content

Commit 10fcc4a

Browse files
committed
Copying Tom's ideas
1 parent 3b0a861 commit 10fcc4a

File tree

4 files changed

+111
-111
lines changed

4 files changed

+111
-111
lines changed

raycloudtools/rayextract/rayextract.cpp

+43-34
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
// Author: Thomas Lowe
66
#include "raylib/extraction/rayclusters.h"
77
#include "raylib/extraction/rayforest.h"
8+
#include "raylib/extraction/rayleaves.h"
89
#include "raylib/extraction/rayterrain.h"
910
#include "raylib/extraction/raytrees.h"
1011
#include "raylib/extraction/raytrunks.h"
11-
#include "raylib/extraction/rayleaves.h"
1212
#include "raylib/raycloud.h"
1313
#include "raylib/rayforestgen.h"
1414
#include "raylib/rayforeststructure.h"
@@ -25,7 +25,8 @@ static std::string extract_type;
2525

2626
void usage(int exit_code = 1)
2727
{
28-
const bool none = extract_type != "terrain" && extract_type != "trunks" && extract_type != "forest" && extract_type != "trees" && extract_type != "leaves";
28+
const bool none = extract_type != "terrain" && extract_type != "trunks" && extract_type != "forest" &&
29+
extract_type != "trees" && extract_type != "leaves";
2930
// clang-format off
3031
std::cout << "Extract natural features into a text file or mesh file" << std::endl;
3132
std::cout << "usage:" << std::endl;
@@ -54,21 +55,22 @@ void usage(int exit_code = 1)
5455
std::cout << " --max_diameter 0.9 - (-m) maximum trunk diameter in segmenting trees" << std::endl;
5556
std::cout << " --crop_length 1.0 - (-p) crops small branches to this distance from end" << std::endl;
5657
std::cout << " --distance_limit 1 - (-d) maximum distance between neighbour points in a tree" << std::endl;
57-
std::cout << " --height_min 2 - (-h) minimum height counted as a tree" << std::endl;
58-
std::cout << " --min_radius 0.01 - (-r) minimum tree radius to consider" << std::endl;
58+
std::cout << " --height_min 2 - (-h) minimum height tree to reconstruct" << std::endl;
59+
std::cout << " --radius_min 0 - (-r) minimum radius tree to reconstruct" << std::endl;
5960
std::cout << " --girth_height_ratio 0.12 - (-i) the amount up tree's height to estimate trunk girth" << std::endl;
6061
std::cout << " --global_taper 0.024 - (-a) force a taper value (diameter per length) for trees under global_taper_factor of max tree height. Use 0 to estimate global taper from the data" << std::endl;
6162
std::cout << " --global_taper_factor 0.3- (-o) 1 estimates same taper for whole scan, 0 is per-tree tapering. Like a soft cutoff at this amount of max tree height" << std::endl;
6263
std::cout << " --gravity_factor 0.3 - (-f) larger values preference vertical trees" << std::endl;
6364
std::cout << " --branch_segmentation- (-b) _segmented.ply is per branch segment" << std::endl;
6465
std::cout << " --grid_width 10 - (-w) crops results assuming cloud has been gridded with given width" << std::endl;
65-
std::cout << " --grid_origin 0,0,0 - location of origin within grid cell that overlaps it. Defaults to a cell-centre origin (at grid_width/2 in each axis) matching raysplit grid. 0,0,0 is for a vertex origin." << std::endl;
6666
std::cout << " --use_rays - (-u) use rays to reduce trunk radius overestimation in noisy cloud data" << std::endl;
67-
std::cout << " (for internal constants -c -g -s see source file rayextract)" << std::endl;
67+
std::cout << " (for internal constants -c -g -s -d see source file rayextract)" << std::endl;
6868
// These are the internal parameters that I don't expose as they are 'advanced' only, you shouldn't need to adjust them
6969
// std::cout << " --cylinder_length_to_width 4- (-c) how slender the cylinders are" << std::endl;
7070
// std::cout << " --gap_ratio 0.016 - (-g) will split for lateral gaps at this multiple of branch length" << std::endl;
7171
// std::cout << " --span_ratio 4.5 - (-s) will split when branch width spans this multiple of radius" << std::endl;
72+
// std::cout << " --grid_origin 0,0 - (-d) location of grid corner (any of them) when grid_width used, use 0,0 for grid with vertex at 0,0.
73+
// Default is -grid_width/2,-grid_width/2 to match the grid in raysplit grid" << std::endl;
7274
}
7375
if (extract_type == "leaves" || none)
7476
{
@@ -94,33 +96,33 @@ int rayExtract(int argc, char *argv[])
9496
}
9597
ray::FileArgument cloud_file, mesh_file, trunks_file, trees_file, leaf_file;
9698
ray::TextArgument forest("forest"), trees("trees"), trunks("trunks"), terrain("terrain"), leaves("leaves");
97-
98-
ray::Vector3dArgument grid_origin;
99-
ray::OptionalKeyValueArgument grid_origin_option("grid_origin", &grid_origin);
10099
ray::OptionalKeyValueArgument groundmesh_option("ground", 'g', &mesh_file);
101100
ray::OptionalKeyValueArgument trunks_option("trunks", 't', &trunks_file);
102101
ray::DoubleArgument gradient(0.001, 1000.0, 1.0), global_taper(0.0, 1.0), global_taper_factor(0.0, 1.0);
103102
ray::OptionalKeyValueArgument gradient_option("gradient", 'g', &gradient);
104-
ray::OptionalFlagArgument exclude_rays("exclude_rays", 'e'), segment_branches("branch_segmentation", 'b'), stalks("stalks", 's'), use_rays("use_rays", 'u');
103+
ray::OptionalFlagArgument exclude_rays("exclude_rays", 'e'), segment_branches("branch_segmentation", 'b'),
104+
stalks("stalks", 's'), use_rays("use_rays", 'u');
105105
ray::DoubleArgument width(0.01, 10.0, 0.25), drop(0.001, 1.0), max_gradient(0.01, 5.0), min_gradient(0.01, 5.0);
106106

107107
ray::DoubleArgument max_diameter(0.01, 100.0), distance_limit(0.01, 10.0), height_min(0.01, 1000.0),
108-
min_diameter(0.01, 100.0), leaf_area(0.00001, 1.0, 0.002), leaf_droop(0.0, 10.0, 0.1), crop_length(0.01, 100.0);;
109-
ray::DoubleArgument girth_height_ratio(0.001, 0.5), length_to_radius(0.01, 10000.0), cylinder_length_to_width(0.1, 20.0), gap_ratio(0.01, 10.0),
110-
span_ratio(0.01, 10.0), min_radius(0.01, 100.0);
111-
ray::DoubleArgument gravity_factor(0.0, 100.0), grid_width(1.0, 100000.0),
112-
grid_overlap(0.0, 0.9);
108+
radius_min(0.0, 1000.0), min_diameter(0.01, 100.0), leaf_area(0.00001, 1.0, 0.002), leaf_droop(0.0, 10.0, 0.1),
109+
crop_length(0.01, 100.0);
110+
;
111+
ray::DoubleArgument girth_height_ratio(0.001, 0.5), length_to_radius(0.01, 10000.0),
112+
cylinder_length_to_width(0.1, 20.0), gap_ratio(0.01, 10.0), span_ratio(0.01, 10.0);
113+
ray::DoubleArgument gravity_factor(0.0, 100.0), grid_width(1.0, 100000.0), grid_overlap(0.0, 0.9);
114+
ray::Vector2dArgument grid_origin(-1e10, 1e10);
113115
ray::OptionalKeyValueArgument max_diameter_option("max_diameter", 'm', &max_diameter);
114116
ray::OptionalKeyValueArgument crop_length_option("crop_length", 'n', &crop_length);
115117
ray::OptionalKeyValueArgument distance_limit_option("distance_limit", 'd', &distance_limit);
116118
ray::OptionalKeyValueArgument height_min_option("height_min", 'h', &height_min);
119+
ray::OptionalKeyValueArgument radius_min_option("radius_min", 'r', &radius_min);
117120
ray::OptionalKeyValueArgument girth_height_ratio_option("girth_height_ratio", 'i', &girth_height_ratio);
118121
ray::OptionalKeyValueArgument cylinder_length_to_width_option("cylinder_length_to_width", 'c',
119122
&cylinder_length_to_width);
120-
121-
ray::OptionalKeyValueArgument min_radius_option("min_radius", 'r', &min_radius);
122123
ray::OptionalKeyValueArgument gap_ratio_option("gap_ratio", 'g', &gap_ratio);
123124
ray::OptionalKeyValueArgument span_ratio_option("span_ratio", 's', &span_ratio);
125+
ray::OptionalKeyValueArgument grid_origin_option("grid_origin", 'd', &grid_origin);
124126
ray::OptionalKeyValueArgument gravity_factor_option("gravity_factor", 'f', &gravity_factor);
125127
ray::OptionalKeyValueArgument grid_width_option("grid_width", 'w', &grid_width);
126128
ray::OptionalKeyValueArgument global_taper_option("global_taper", 'a', &global_taper);
@@ -142,11 +144,12 @@ int rayExtract(int argc, char *argv[])
142144
{ &groundmesh_option, &trunks_option, &width_option, &smooth_option, &drop_option, &verbose });
143145
bool extract_trees = ray::parseCommandLine(
144146
argc, argv, { &trees, &cloud_file, &mesh_file },
145-
{ &max_diameter_option, &distance_limit_option, &height_min_option, &crop_length_option, &girth_height_ratio_option,
146-
&cylinder_length_to_width_option, &gap_ratio_option, &span_ratio_option, &gravity_factor_option,
147-
&segment_branches, &grid_width_option, &global_taper_option, &global_taper_factor_option, &use_rays, &verbose,
148-
&grid_origin_option, &min_radius_option });
149-
bool extract_leaves = ray::parseCommandLine(argc, argv, { &leaves, &cloud_file, &trees_file }, { &leaf_option, &leaf_area_option, &leaf_droop_option, &stalks });
147+
{ &max_diameter_option, &distance_limit_option, &height_min_option, &radius_min_option, &crop_length_option,
148+
&girth_height_ratio_option, &cylinder_length_to_width_option, &gap_ratio_option, &span_ratio_option,
149+
&grid_origin_option, &gravity_factor_option, &segment_branches, &grid_width_option, &global_taper_option,
150+
&global_taper_factor_option, &use_rays, &verbose });
151+
bool extract_leaves = ray::parseCommandLine(argc, argv, { &leaves, &cloud_file, &trees_file },
152+
{ &leaf_option, &leaf_area_option, &leaf_droop_option, &stalks });
150153

151154

152155
if (!extract_trunks && !extract_forest && !extract_terrain && !extract_trees && !extract_leaves)
@@ -199,6 +202,10 @@ int rayExtract(int argc, char *argv[])
199202
{
200203
params.height_min = height_min.value();
201204
}
205+
if (radius_min_option.isSet())
206+
{
207+
params.radius_min = radius_min.value();
208+
}
202209
if (crop_length_option.isSet())
203210
{
204211
params.crop_length = crop_length.value();
@@ -226,6 +233,12 @@ int rayExtract(int argc, char *argv[])
226233
if (grid_width_option.isSet())
227234
{
228235
params.grid_width = grid_width.value();
236+
params.grid_origin =
237+
-Eigen::Vector2d(grid_width.value(), grid_width.value()) / 2.0; // the centred grid used by raysplit grid
238+
}
239+
if (grid_origin_option.isSet())
240+
{
241+
params.grid_origin = grid_origin.value();
229242
}
230243
if (global_taper_option.isSet())
231244
{
@@ -235,14 +248,6 @@ int rayExtract(int argc, char *argv[])
235248
{
236249
params.global_taper_factor = global_taper_factor.value();
237250
}
238-
if (grid_origin_option.isSet())
239-
{
240-
params.grid_origin = grid_origin.value();
241-
}
242-
if (min_radius_option.isSet())
243-
{
244-
params.min_radius = min_radius.value();
245-
}
246251
params.use_rays = use_rays.isSet();
247252
params.segment_branches = segment_branches.isSet();
248253

@@ -259,11 +264,15 @@ int rayExtract(int argc, char *argv[])
259264
ray::ForestStructure forest;
260265
if (!forest.load(cloud_file.nameStub() + "_trees.txt"))
261266
{
262-
usage();
267+
std::cerr << "Unable to load "
268+
<< cloud_file.nameStub() +
269+
"_trees.txt to generate tree mesh file, this could mean that there were no trees output"
270+
<< std::endl;
271+
exit(true);
263272
}
264273
ray::Mesh tree_mesh;
265274
forest.generateSmoothMesh(tree_mesh, -1, 1, 1, 1);
266-
ray::writePlyMesh(cloud_file.nameStub() + "_trees_mesh.ply", tree_mesh, true);
275+
ray::writePlyMesh(cloud_file.nameStub() + "_trees_mesh.ply", tree_mesh, true);
267276
}
268277
// extract the tree locations from a larger, aerial view of a forest
269278
else if (extract_forest)
@@ -321,8 +330,8 @@ int rayExtract(int argc, char *argv[])
321330
}
322331
else if (extract_leaves)
323332
{
324-
ray::generateLeaves(cloud_file.nameStub(), trees_file.name(), leaf_file.name(),
325-
leaf_area.value(), leaf_droop.value(), stalks.isSet());
333+
ray::generateLeaves(cloud_file.nameStub(), trees_file.name(), leaf_file.name(), leaf_area.value(),
334+
leaf_droop.value(), stalks.isSet());
326335
}
327336
else
328337
{

0 commit comments

Comments
 (0)