Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docker #69

Merged
merged 5 commits into from
Apr 16, 2024
Merged
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
4 changes: 4 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "Vegetation",
"image": "2024m1vegetation:latest"
}
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*.toc

# Project files
temp/
build/
html/
latex/
Expand All @@ -24,5 +25,6 @@ output/
# Python virtual environment
.venv/

# MacOS
.DS_Store
# macOS
.DS_Store

27 changes: 27 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FROM ubuntu:24.04

# Copy project files
COPY . /vegetation
WORKDIR /vegetation

# Set the timezone to Europe/Paris
ENV TZ=Europe/Paris

# Install system dependencies
RUN apt-get update && apt-get install -y \
wget \
build-essential \
cmake \
git \
libmpfr-dev \
libboost-dev \
libcurl4-openssl-dev \
python3-pip \
libcgal-dev \
libfmt-dev \
libspdlog-dev && \
rm -rf /var/lib/apt/lists/*




52 changes: 24 additions & 28 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,13 @@

The goal of this project is to develop a tool that integrates vegetation (trees) into 3D urban models in order to improve the efficiency of thermal simulations.

This reposirory contains:

- include: Header files
- src: Source files
- test: Test files

== Installation and Usage

=== Install Required Packages

This project uses link:https://www.cgal.org[CGAL], link:https://curl.se/[curl] and link:https://github.com/nlohmann/json[nlohmann/json libraries]. Go check them out if you don't have them locally installed.
This project uses link:https://www.cgal.org[CGAL], link:https://curl.se/[curl].

If you don't want to install them globally on your local machine you can use Miniforge to create a new environment with the required packages:
If you don't want to install dependencies globally on your local machine you can use Miniforge or venv to create a new environment with the required packages:

=== Set up an environment
We provide here two example of environment, Mamba and venv
Expand Down Expand Up @@ -52,42 +46,44 @@ source .venv/bin/activate
With the environment set up, install the required packages:

```bash
pip install -r requirements.txt
mamba install -c conda-forge cgal-cpp fmt spdlog mpfr boost-cpp curl -y
```

=== Alternatively you can use a Docker container:
```bash
docker build -t 2024m1vegetation:latest
docker run -it 2024m1vegetation:latest
```

Note: on VsCode you can use the Remote - Containers extension to reopen the project in a container.

=== Build the Project

Configure and build the project using CMake:
```bash
# Configure CMake
cmake --preset default
cd build
# Clean the build directory
rm -rf *

# Build the project
cmake --build --preset default
cmake ..

# Test the build
ctest --preset default
```
# Compile the project
make

=== Usage (currently a basic alpha wrapper)

To use the alpha wrapper, run the following command:

```bash
./build/default/bin/wrap <input_file> <alpha> <offset>
# Run the tests
make test
```

The output mesh will be saved in the `/output`` folder.

=== Example

Here's an example of how to use the alpha wrapper:
=== Usage

```bash
./build/default/bin/wrap data/trees/oranger.off 10
./build/run
```

=== Notes
The `config.json` file contains the gps coordinates of the 2 corners of the area to pull data from OpenSTreetMap.

The output mesh will be saved in the `/temp` directory.

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

Expand Down
18 changes: 9 additions & 9 deletions config.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"A": {
"latitude": 48.578702,
"longitude": 7.739103
},
"B": {
"latitude": 48.587756,
"longitude": 7.756632
}
}
"A": {
"latitude": 48.5858,
"longitude": 7.7541
},
"B": {
"latitude": 48.5802,
"longitude": 7.7429
}
}
Binary file added data/tree/leafless/arbre1.stl
Binary file not shown.
Binary file added data/tree/leafless/arbre2.stl
Binary file not shown.
Binary file added data/tree/leafless/bois.stl
Binary file not shown.
Binary file added data/tree/leafless/mix.stl
Binary file not shown.
Binary file added data/tree/leafless/oranger.stl
Binary file not shown.
Binary file added data/tree/leafy/arbre1.stl
Binary file not shown.
Binary file added data/tree/leafy/arbre2.stl
Binary file not shown.
Binary file added data/tree/leafy/bois.stl
Binary file not shown.
Binary file added data/tree/leafy/mix.stl
Binary file not shown.
Binary file added data/tree/leafy/oranger.stl
Binary file not shown.
128 changes: 128 additions & 0 deletions include/mesh.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#ifndef MESH_HPP
#define MESH_HPP

#include "tree.hpp"
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/IO/polygon_soup_io.h>
#include <CGAL/Polygon_mesh_processing/bbox.h>
#include <CGAL/Real_timer.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/alpha_wrap_3.h>
#include <array>
#include <iostream>
#include <string>
#include <vector>

using K = CGAL::Exact_predicates_inexact_constructions_kernel;
using Point_3 = K::Point_3;
using Mesh = CGAL::Surface_mesh<Point_3>;

class TreeMesh {
public:
void wrap_tree(const Tree &t) {
std::string filePath = "../data/tree/";
std::string season = t.getSeason();
std::string species = t.getSpecies();

if (season == "spring" || season == "summer") {
filePath += "leafy/";
} else {
filePath += "leafless/";
}

// if (species == "Acer pseudoplatanus") {
// filePath += "arbre1.off";
// }
// ...
filePath += "arbre1.stl";
filename = "arbre1.stl";

double relative_alpha;
double relative_offset = 600;

switch (M_lod) {
case 0:
relative_alpha = 0.1;
break;
case 1:
relative_alpha = 20;
break;
case 2:
relative_alpha = 100;
break;
default:
break;
}

CGAL::data_file_path(filePath);
std::vector<Point_3> points;
std::vector<std::array<int, 3>> faces;
std::vector<std::array<int, 3>> edges;
CGAL::Bbox_3 bbox;

if (!CGAL::IO::read_polygon_soup(filePath, points, faces) ||
faces.empty()) {
std::cerr << "Invalid input." << std::endl;
exit(1);
}

for (const Point_3 &p : points)
bbox += p.bbox();
const double diag_length =
std::sqrt(CGAL::square(bbox.xmax() - bbox.xmin()) +
CGAL::square(bbox.ymax() - bbox.ymin()) +
CGAL::square(bbox.zmax() - bbox.zmin()));

const double alpha = diag_length / relative_alpha;
const double offset = diag_length / relative_offset;

// scale the points depending on the tree object

// for (auto &point : points) {
// point = Point_3(point.x(), point.y(), point.z());
// }

CGAL::Real_timer ti;
ti.start();

CGAL::alpha_wrap_3(points, faces, alpha, offset, M_wrap);

ti.stop();

// std::cout << "Result: " << num_vertices(M_wrap) << " vertices, "
// << num_faces(M_wrap) << " faces" << std::endl;
// std::cout << "Took " << ti.time() << " s." << std::endl;
}

void setLod(int lod) { M_lod = lod; }

std::string getFilename() const { return filename; }
int getLod() const { return M_lod; }
Mesh getWrap() const { return M_wrap; }

void dumpMesh(const Tree &t) const {

std::string output_dir = "../temp/";

std::string input_name = std::string(filename);
input_name = input_name.substr(input_name.find_last_of("/") + 1,
input_name.length() - 1);
input_name = input_name.substr(0, input_name.find_last_of("."));

std::string output_name =
output_dir + input_name + "_" +
std::to_string(static_cast<int>(M_lod)) + "_" +
std::to_string(static_cast<int>(t.getX())) + "_" +
std::to_string(static_cast<int>(t.getY())) + ".stl";
// std::cout << "Writing to " << output_name << std::endl;
CGAL::IO::write_polygon_mesh(output_name, M_wrap,
CGAL::parameters::stream_precision(17));
}

private:
int M_lod;
Mesh M_wrap;
std::string filename;
};

#endif
5 changes: 5 additions & 0 deletions include/query.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ class Query {
// Perform the Overpass query
void perform_query();

std::array<double, 2> getRefPt() const {
std::array<double, 2> ref = {min_lat, max_lat};
return ref;
}

nlohmann::json get_query_result();
};

Expand Down
21 changes: 20 additions & 1 deletion include/tree.hpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
#ifndef TREE_HPP
#define TREE_HPP

#include "WGS84toCartesian.hpp"
#include "json.hpp"
#include "query.hpp"
#include <string>

class TreeMesh;
class Tree {
private:
protected:
long id;
double lat;
double lon;
std::string genus;
std::string species;
std::string season;
double height;
double circumference;
double diameter_crown;
double x, y;
TreeMesh *mesh;

public:
// Default constructor
Expand All @@ -33,6 +39,9 @@ class Tree {
double getHeight() const { return height; }
double getCircumference() const { return circumference; }
double getDiameterCrown() const { return diameter_crown; }
std::string getSeason() const { return season; }
double getX() const { return x; }
double getY() const { return y; }

// Setters
void setId(long id) { this->id = id; }
Expand All @@ -47,6 +56,16 @@ class Tree {
void setDiameterCrown(double diameter_crown) {
this->diameter_crown = diameter_crown;
}
void computeXY(const Query &q) {
std::array<double, 2> ref = q.getRefPt();
std::array<double, 2> cartesianPosition =
wgs84::toCartesian({ref[0], ref[1]} /* reference position */,
{lon, lat} /* position to be converted */);
x = cartesianPosition[0];
y = cartesianPosition[1];
}
void setMesh(TreeMesh &m) { this->mesh = &m; }
TreeMesh &getMesh() { return *mesh; }
};

Tree createTreeFromJson(const nlohmann::json &treeJson);
Expand Down
13 changes: 13 additions & 0 deletions query_result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": 0.6,
"generator": "Overpass API 0.7.62.1 084b4234",
"osm3s": {
"timestamp_osm_base": "2024-04-16T08:36:06Z",
"copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL."
},
"elements": [



]
}
1 change: 0 additions & 1 deletion requirements.txt

This file was deleted.

13 changes: 13 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "../include/config.hpp"
#include "../include/json_helpers.hpp"
#include "../include/mesh.hpp"
#include "../include/query.hpp"
#include "../include/tree.hpp"
// #include <cpr/cpr.h>
Expand Down Expand Up @@ -36,5 +37,17 @@ int main(int argc, char **argv) {
<< std::endl;
}

for (auto &tree : treeLibrary) {
tree.computeXY(query);
// std::cout << "Tree X: " << tree.getX() << std::endl;
// std::cout << "Tree Y: " << tree.getY() << std::endl;

TreeMesh mesh;
mesh.setLod(0);
mesh.wrap_tree(tree);
tree.setMesh(mesh);
mesh.dumpMesh(tree);
}

return 0;
}
Loading