Skip to content

Commit

Permalink
Merge pull request #79 from master-csmi/73-missing-data
Browse files Browse the repository at this point in the history
73 missing data
  • Loading branch information
giuliocrp authored May 22, 2024
2 parents 3df87f6 + e8cc578 commit 9b2a865
Show file tree
Hide file tree
Showing 23 changed files with 168 additions and 58 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ endif()
set(requiredlibs)

# Find libraries
find_package(CGAL REQUIRED)
find_package(CGAL REQUIRED COMPONENTS Core)
if(CGAL_FOUND)
set(requiredlibs ${requiredlibs} ${CGAL_3RD_PARTY_LIBRARIES})
set(requiredlibs ${requiredlibs} CGAL::CGAL CGAL::CGAL_Core ${CGAL_3RD_PARTY_LIBRARIES})
else()
message(STATUS "This program requires the CGAL library, and will not be compiled.")
return()
Expand Down
18 changes: 15 additions & 3 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,27 @@ Use the configuration file `config.json` to specify:

- the base name of the output file `output_file` saved in the `/output` directory

Use the `trees.json` file to specify the genus and height of the trees to be used in the simulation.

Then run the program:
- `known_genus` is a list of genus for which we have a base mesh
- `cedrus_like` is a list of the genus for which the cedrus mesh model will be used
- etc.

If you wish you can mesh your own tree model using link:https://doc.cgal.org/latest/Alpha_wrap_3/index.html[CGAL Alpha Wrapper] by running:

```bash
./build/wrap Genus.stl <alpha> <offset>
```

and move the result to the `tree_ref` directory. Then add the genus to the `known_genus` in the `trees.json` file.

Finnaly run the program:
```bash
cd build
./run
```

The output mesh and some metrics will be saved in the `/output` directory (which is automatically
created if needed).
The output mesh and some metrics will be saved in the `/output` directory (which is automatically created if needed).

You can visualize the output mesh with **Meshlab** or any other mesh viewer. (Note: Meshlab does not work well with Wayland.)

Expand Down
15 changes: 1 addition & 14 deletions include/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,7 @@ class Config {
double default_height() const { return M_default_height; }
std::string bbox() const { return M_bbox; }
int LOD() const { return M_LOD; }
std::vector<double> bbox_coords() const {
std::vector<double> coords;
std::string delimiter = ",";
size_t pos = 0;
std::string token;
std::string bbox = M_bbox; // Create a local copy of M_bbox
while ((pos = bbox.find(delimiter)) != std::string::npos) {
token = bbox.substr(0, pos);
coords.push_back(std::stod(token));
bbox.erase(0, pos + delimiter.length());
}
coords.push_back(std::stod(bbox));
return coords;
}
std::vector<double> bbox_coords() const;
};

std::ostream &operator<<(std::ostream &os, const Config &config);
Expand Down
3 changes: 3 additions & 0 deletions include/tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class Tree {
double M_diameter_crown;
double M_x, M_y;
Mesh M_wrap;
std::vector<std::string> M_known_genus, M_cedrus_like, M_acer_like,
M_liquidambar_like, M_quercus_like;

public:
// Default constructor
Expand Down Expand Up @@ -71,6 +73,7 @@ class Tree {

void computeXY(double ref_lat, double ref_lon);
void wrap(int lod);
void load_data(const std::string &filename);
};

Tree createTreeFromJson(const nlohmann::json &treeJson);
Expand Down
59 changes: 56 additions & 3 deletions report.tex
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
{]}{{{\color{delim}{]}}}}{1},
}



\setlength{\parskip}{1em}

\lstset{frame=single, showstringspaces=false, columns=fixed, basicstyle={\ttfamily}, commentstyle={\it}, numbers=left, tabsize=4}
Expand Down Expand Up @@ -238,7 +240,7 @@ \subsection{Data Acquisition}
"default_height": 10,
"default_genus": "Platanus",
"output_name": "republique"
}
}
\end{lstlisting}

Where :
Expand Down Expand Up @@ -289,6 +291,42 @@ \subsection{Tree Library}
of tree objects. Each tree object will contain the tree's metadata (location, species, height,
leave density, etc.).

Additionally, since it's not feasible to have a mesh model for each species of trees,
we will use the \texttt{trees.json} file to specify the genus
categories for the meshing of the trees. \\

\newpage

\begin{lstlisting}[language=json]
{
"known_genus": [
"Abies",
"Acer",
"Aesculus",
...
],
"cedrus_like": [
"Chaemacyparis",
"Cupressus",
...
],
"acer_like": ["Fadus", "Metasequoia", "Sequoiadendron", "Thuja", "Tsuga"],
"liquidambar_like": ["Liriodendron", "Pyrus", "Alnus", "Ostrya"],
"quercus_like": [
"Corylus",
"Carya",
"Fagus",
...
]
}
\end{lstlisting}

\begin{itemize}
\item \texttt{known\_genus} is a list of the genus for which we have a mesh model.
\item \texttt{cedrus\_like} is a list of the genus for which the cedrus mesh model will be used.
\item etc.
\end{itemize}

\subsection{Tree Model Generation}
Using the CGAL 3D Alpha Wrapping \cite{cgal_alpha_wrapper} algorithm we will produce
reference tree meshes for each level of detail (LOD) from 0 to 3 to avoid computing
Expand All @@ -307,15 +345,15 @@ \subsection{Tree Model Generation}
can be used as follows:
(50 is the alpha value and 600 is the offset value)

\begin{lstlisting}
\begin{lstlisting}[language=bash]
./build/wrap tree_ref/raw_tree/Ginkgo.stl 50 600
\end{lstlisting}


Additionally, to wrap all the trees in a directory, the \texttt{wrap\_all.sh} script
can be used:

\begin{lstlisting}
\begin{lstlisting}[language=bash]
#!/bin/bash

# Directory containing the raw STL files
Expand Down Expand Up @@ -429,6 +467,18 @@ \subsection{Metrics}
the \texttt{output} directory. \\
These results will be analyzed more thoroughly in the \textbf{Results} section.

Example of the result's metrics for \texttt{grande\_ile\_LOD1.txt}:

\begin{lstlisting}
Area: 561545 meters
Total number of trees: 409
Number of tree which had no height: 67
Number of tree which had no genus: 27
Number of vertices: 241791
Number of faces: 482686
Time to mesh: 155.965 seconds, (2.59942 minutes)
\end{lstlisting}

\section{Implementation}

\subsection{Querying data}
Expand Down Expand Up @@ -462,6 +512,8 @@ \subsection{Class Tree}
double M_diameter_crown;
double M_x, M_y;
Mesh M_wrap;
std::vector<std::string> M_known_genus, M_cedrus_like, M_acer_like,
M_liquidambar_like, M_quercus_like;

public:
// Default constructor
Expand Down Expand Up @@ -503,6 +555,7 @@ \subsection{Class Tree}

void computeXY(double ref_lat, double ref_lon);
void wrap(int lod);
void load_data(const std::string &filename);
};

Tree createTreeFromJson(const nlohmann::json &treeJson);
Expand Down
15 changes: 15 additions & 0 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,21 @@ Config::Config(std::string const &filename) {
}
}

std::vector<double> Config::bbox_coords() const {
std::vector<double> coords;
std::string delimiter = ",";
size_t pos = 0;
std::string token;
std::string bbox = M_bbox; // Create a local copy of M_bbox
while ((pos = bbox.find(delimiter)) != std::string::npos) {
token = bbox.substr(0, pos);
coords.push_back(std::stod(token));
bbox.erase(0, pos + delimiter.length());
}
coords.push_back(std::stod(bbox));
return coords;
}

Config::~Config() {}

std::ostream &operator<<(std::ostream &os, const Config &config) {
Expand Down
8 changes: 6 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ int main(int argc, char **argv) {
std::cout << "Computing the union of tree meshes ..." << std::endl;
t.start();
for (auto &tree : treeLibrary) {
tree.load_data("../trees.json");
tree.computeXY(ref_lat, ref_lon);

// std::cout << tree << std::endl;
Expand Down Expand Up @@ -126,9 +127,11 @@ int main(int argc, char **argv) {
std::ofstream output(filename);
CGAL::IO::write_STL(output, finalMesh);

std::cout << "" << std::endl;
std::cout << "Final mesh: " << num_vertices(finalMesh) << " vertices, "
<< num_faces(finalMesh) << " faces" << std::endl;
std::cout << "Took " << t.time() << " s." << std::endl;
std::cout << "Took " << t.time() << " s. (" << t.time() / 60.0
<< " minutes)" << std::endl;
std::cout << "Final mesh written to " << filename << std::endl;

// Metrics export
Expand All @@ -142,7 +145,8 @@ int main(int argc, char **argv) {
metrics << "Number of tree which had no genus: " << nNoGenus << std::endl;
metrics << "Number of vertices: " << num_vertices(finalMesh) << std::endl;
metrics << "Number of faces: " << num_faces(finalMesh) << std::endl;
metrics << "Time to mesh: " << t.time() << " seconds" << std::endl;
metrics << "Time to mesh: " << t.time() << " seconds, (" << t.time() / 60.0
<< " minutes)" << std::endl;
metrics.close();

std::cout << "Metrics available at " << metrics_filename << std::endl;
Expand Down
63 changes: 29 additions & 34 deletions src/tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,54 +71,49 @@ void Tree::computeXY(double ref_lat, double ref_lon) {
M_y = cartesianPosition[1];
}

void Tree::load_data(const std::string &filename) {
std::ifstream ifile(filename);
if (ifile) {
nlohmann::json data = nlohmann::json::parse(ifile);
M_known_genus = data["known_genus"];
M_cedrus_like = data["cedrus_like"];
M_acer_like = data["acer_like"];
M_liquidambar_like = data["liquidambar_like"];
M_quercus_like = data["quercus_like"];
} else {
std::cerr << "Error opening file: " << filename << std::endl;
}
}

void Tree::wrap(int lod) {
std::string filename = "../tree_ref/";
double scaling_factor_double;
std::vector<Point_3> points;
std::vector<std::array<int, 3>> faces;
CGAL::Bbox_3 bbox;

std::vector<std::string> known_tree = {
"Abies", "Acer", "Aesculus", "Catalpa", "Cedrus",
"Ginkgo", "Gleditsia", "Liquidambar", "Magnolia", "Platanus",
"Quercus", "Taxus", "Tilia"};
std::vector<std::string> conifer = {"Chaemacyparis", "Cupressus",
"Juniperus", "Larix",
"Picea", "Pinus",
"Pseudotsuga", "Chamaecyparis",
"Calocedrus"}; // -> Cedrus
std::vector<std::string> hetre = {"Fadus"}; // -> Acer
std::vector<std::string> tulipier = {"Liriodendron", "Fraxinus",
"Pyrus"}; // -> Liquidambar
std::vector<std::string> big_tree = {"Corylus", "Carya", "Fagus", "Celtis",
"Ailanthus"}; // -> Quercus
std::vector<std::string> long_tree = {"Alnus"}; // -> Ginkgo
std::vector<std::string> prunus = {"Prunus"}; // -> Aesculus

if (std::find(known_tree.begin(), known_tree.end(), M_genus) !=
known_tree.end()) {
if (std::find(M_known_genus.begin(), M_known_genus.end(), M_genus) !=
M_known_genus.end()) {
filename += M_genus;
} else if (std::find(conifer.begin(), conifer.end(), M_genus) !=
conifer.end()) {
} else if (std::find(M_cedrus_like.begin(), M_cedrus_like.end(), M_genus) !=
M_cedrus_like.end()) {
filename += "Cedrus";
} else if (std::find(hetre.begin(), hetre.end(), M_genus) != hetre.end()) {
} else if (std::find(M_acer_like.begin(), M_acer_like.end(), M_genus) !=
M_acer_like.end()) {
filename += "Acer";
} else if (std::find(tulipier.begin(), tulipier.end(), M_genus) !=
tulipier.end()) {
} else if (std::find(M_liquidambar_like.begin(), M_liquidambar_like.end(),
M_genus) != M_liquidambar_like.end()) {
filename += "Liquidambar";
} else if (std::find(big_tree.begin(), big_tree.end(), M_genus) !=
big_tree.end()) {
} else if (std::find(M_quercus_like.begin(), M_quercus_like.end(),
M_genus) != M_quercus_like.end()) {
filename += "Quercus";
} else if (std::find(long_tree.begin(), long_tree.end(), M_genus) !=
long_tree.end()) {
filename += "Ginkgo";
} else if (std::find(prunus.begin(), prunus.end(), M_genus) !=
prunus.end()) {
filename += "Aesculus";
} else {
std::cerr << "Unknown genus: " << M_genus << std::endl;
exit(1);
std::cout << "Genus : " << M_genus
<< ", not found in trees.json database, using Quercus instead"
<< std::endl;
filename += "Quercus";
}

switch (lod) {
case 0:
filename += "_0_600.stl";
Expand Down
Binary file modified tree_ref/raw_tree/Acer2.stl
Binary file not shown.
Binary file modified tree_ref/raw_tree/Aesculus.stl
Binary file not shown.
Binary file modified tree_ref/raw_tree/Catalpa.stl
Binary file not shown.
Binary file modified tree_ref/raw_tree/Cedrus.stl
Binary file not shown.
Binary file modified tree_ref/raw_tree/Ginkgo.stl
Binary file not shown.
Binary file modified tree_ref/raw_tree/Gleditsia.stl
Binary file not shown.
Binary file modified tree_ref/raw_tree/Liquidambar.stl
Binary file not shown.
Binary file modified tree_ref/raw_tree/Magnolia.stl
Binary file not shown.
Binary file modified tree_ref/raw_tree/Platanus.stl
Binary file not shown.
Binary file modified tree_ref/raw_tree/Quercus.stl
Binary file not shown.
Binary file modified tree_ref/raw_tree/Taxus.stl
Binary file not shown.
Binary file modified tree_ref/raw_tree/Tilia.stl
Binary file not shown.
Binary file modified tree_ref/raw_tree/arbre1.stl
Binary file not shown.
Binary file modified tree_ref/raw_tree/bois.stl
Binary file not shown.
41 changes: 41 additions & 0 deletions trees.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"known_genus": [
"Abies",
"Acer",
"Aesculus",
"Catalpa",
"Cedrus",
"Ginkgo",
"Gleditsia",
"Liquidambar",
"Magnolia",
"Platanus",
"Quercus",
"Taxus",
"Tilia"
],
"cedrus_like": [
"Chaemacyparis",
"Cupressus",
"Juniperus",
"Larix",
"Picea",
"Pinus",
"Pseudotsuga",
"Chamaecyparis",
"Calocedrus"
],
"acer_like": ["Fadus", "Metasequoia", "Sequoiadendron", "Thuja", "Tsuga"],
"liquidambar_like": ["Liriodendron", "Pyrus", "Alnus", "Ostrya"],
"quercus_like": [
"Corylus",
"Carya",
"Fagus",
"Prunus",
"Fraxinus",
"Ailanthus",
"Celtis",
"Carpinus",
"Styphnolobium"
]
}

0 comments on commit 9b2a865

Please sign in to comment.