Commit dd44aaae authored by Pierre Aubert's avatar Pierre Aubert
Browse files

Add base of test on generic tree (Quadtree and octree but with N dimentions)

parent c49803f6
Pipeline #96675 passed with stages
in 1 minute and 22 seconds
...@@ -11,7 +11,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) ...@@ -11,7 +11,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
phoenix_create_find_header(PhoenixGraph Graph.h "") phoenix_create_find(PhoenixGraph phoenix_graph Graph.h "")
add_subdirectory(src) add_subdirectory(src)
......
...@@ -8,4 +8,5 @@ add_subdirectory(TEST_DOT_LOOP) ...@@ -8,4 +8,5 @@ add_subdirectory(TEST_DOT_LOOP)
add_subdirectory(TEST_DOT_TOTAL_LOOP) add_subdirectory(TEST_DOT_TOTAL_LOOP)
add_subdirectory(TEST_DOT_REMOVE) add_subdirectory(TEST_DOT_REMOVE)
add_subdirectory(TEST_DOT_STR) add_subdirectory(TEST_DOT_STR)
add_subdirectory(TEST_PNTREE_LIGHT)
project(Phoenix) project(Phoenix)
add_executable(test_graph_to_dot main.cpp) add_executable(test_graph_to_dot main.cpp)
target_link_libraries(test_graph_to_dot phoenix_graph)
add_test(NAME TestGraphToDot add_test(NAME TestGraphToDot
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_graph_to_dot) COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_graph_to_dot)
......
project(Phoenix) project(Phoenix)
add_executable(test_graph_to_dot_loop main.cpp) add_executable(test_graph_to_dot_loop main.cpp)
target_link_libraries(test_graph_to_dot_loop phoenix_graph)
add_test(NAME TestGraphToDotLoop add_test(NAME TestGraphToDotLoop
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_graph_to_dot_loop) COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_graph_to_dot_loop)
......
project(Phoenix) project(Phoenix)
add_executable(test_graph_to_dot_remove main.cpp) add_executable(test_graph_to_dot_remove main.cpp)
target_link_libraries(test_graph_to_dot_remove phoenix_graph)
add_test(NAME TestGraphToDotRemove add_test(NAME TestGraphToDotRemove
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_graph_to_dot_remove) COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_graph_to_dot_remove)
......
project(Phoenix) project(Phoenix)
add_executable(test_graph_to_dot_str main.cpp) add_executable(test_graph_to_dot_str main.cpp)
target_link_libraries(test_graph_to_dot_str phoenix_graph)
add_test(NAME TestGraphToDotStr add_test(NAME TestGraphToDotStr
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_graph_to_dot_str) COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_graph_to_dot_str)
......
project(Phoenix) project(Phoenix)
add_executable(test_graph_to_dot_total_loop main.cpp) add_executable(test_graph_to_dot_total_loop main.cpp)
target_link_libraries(test_graph_to_dot_total_loop phoenix_graph)
add_test(NAME TestGraphToDotTotalLoop add_test(NAME TestGraphToDotTotalLoop
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_graph_to_dot_total_loop) COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_graph_to_dot_total_loop)
......
project(Phoenix)
cmake_minimum_required(VERSION 3.0)
add_executable(test_pntreelight main.cpp)
target_link_libraries(test_pntreelight phoenix_graph)
add_test(NAME TestPNTreeLight
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_pntreelight
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
/***************************************
Auteur : Pierre Aubert
Mail : aubertp7@gmail.com
Licence : CeCILL-C
****************************************/
#include <iostream>
#include "Tree/PNTreeLight.h"
using namespace std;
#define NB_POINT 8lu
#define NB_POINT_TOTAL (NB_POINT*NB_POINT)
#define NB_POINT_3D 8lu
#define NB_POINT_3D_TOTAL (NB_POINT_3D*NB_POINT_3D*NB_POINT_3D)
///Tests the basis of the quadtree
void testBaseQuadTree(){
size_t nbPoint(NB_POINT);
float dXY(5.0f);
float shift(dXY/2.0f);
float posXY(0.0f), sizeXY(((size_t)(2.0f*shift + ((float)(nbPoint - 1lu))*dXY)));
float posTab[] = {posXY, posXY};
float sizeTab[] = {sizeXY, sizeXY};
PNTreeLight<float, size_t, 2> quadTree(posTab, sizeTab, 1.0f);
size_t tabId[NB_POINT_TOTAL], id;
for(size_t i(0lu); i < NB_POINT_TOTAL; ++i){tabId[i] = i;}
float x, y;
float tabPos[2*NB_POINT_TOTAL];
std::ofstream fs;
fs.open("pointAddedInQuadTree.txt");
if(!fs.is_open()) return;
for(size_t i(0lu); i < nbPoint; ++i){
y = shift + ((float)i)*dXY;
for(size_t j(0lu); j < nbPoint; ++j){
x = shift + ((float)j)*dXY;
tabPos[(i*nbPoint + j)*2lu] = x;
tabPos[(i*nbPoint + j)*2lu + 1lu] = y;
id = i*nbPoint + j;
cerr << "Add point " << x << "," << y << "\t, id = " << id << endl;
fs << x << "\t" << y << "\t0" << endl;
if(!quadTree.addElement(&(tabPos[(i*nbPoint + j)*2lu]), tabId+id)){
cerr << "quadTree.addElement : can't add element : Stop" << endl;
i = nbPoint;
break;
}
}
}
fs.close();
std::string fileTxt("quadTree.txt");
if(quadTree.saveGnuplotData(fileTxt)){
std::cout << "testBaseQuadTree : file '" << fileTxt << "' saved" << std::endl;
}else{
std::cerr << "testBaseQuadTree : can't save file '" << fileTxt << "'" << std::endl;
}
float posLastData[] = {11.0f, 19.0f};
const size_t * data = quadTree.getLastData(posLastData);
if(data != NULL) cout << "testBaseQuadTree : data (11.0, 19.0) = " << *data << endl;
else cout << "testBaseQuadTree : data (11.0, 19.0) = NULL" << endl;
}
///Tests the basis of the quadtree
void testBaseQuadTree3d(){
size_t nbPoint(NB_POINT_3D);
float dXY(5.0f);
float shift(dXY/2.0f);
float posXY(0.0f), sizeXY(((size_t)(2.0f*shift + ((float)(nbPoint - 1lu))*dXY)));
float posTab[] = {posXY, posXY, posXY};
float sizeTab[] = {sizeXY, sizeXY, sizeXY};
PNTreeLight<float, size_t, 3> quadTree(posTab, sizeTab);
size_t tabId[NB_POINT_3D_TOTAL], id;
for(size_t i(0lu); i < NB_POINT_3D_TOTAL; ++i){tabId[i] = i;}
float tabPos[3*NB_POINT_3D_TOTAL];
float x,y,z;
std::ofstream fs;
fs.open("pointAddedInQuadTree3d.txt");
if(!fs.is_open()) return;
for(size_t k(0lu); k < nbPoint; ++k){
z = shift + ((float)k)*dXY;
for(size_t i(0lu); i < nbPoint; ++i){
y = shift + ((float)i)*dXY;
for(size_t j(0lu); j < nbPoint; ++j){
x = shift + ((float)j)*dXY;
id = k*nbPoint*nbPoint + i*nbPoint + j;
// cerr << "Add point " << tabPos[0] << "," << tabPos[1] << "," << tabPos[2] << "\t, id = " << id << endl;
tabPos[(k*nbPoint*nbPoint + i*nbPoint + j)*3lu] = x;
tabPos[(k*nbPoint*nbPoint + i*nbPoint + j)*3lu + 1lu] = y;
tabPos[(k*nbPoint*nbPoint + i*nbPoint + j)*3lu + 2lu] = z;
fs << x << "\t" << y << "\t"<< z << endl;
if(!quadTree.addElement(&(tabPos[(k*nbPoint*nbPoint + i*nbPoint + j)*3lu]), tabId+id)){
cerr << "quadTree.addElement : can't add element : Stop" << endl;
i = nbPoint;
break;
}
}
}
}
fs.close();
std::string fileTxt("quadTree3d.txt");
if(quadTree.saveGnuplotData(fileTxt)){
std::cout << "testBaseQuadTree3d : file '" << fileTxt << "' saved" << std::endl;
}else{
std::cerr << "testBaseQuadTree3d : can't save file '" << fileTxt << "'" << std::endl;
}
float posLastData[] = {11.0f, 19.0f, 10.0f};
const size_t * data = quadTree.getLastData(posLastData);
if(data != NULL) cout << "testBaseQuadTree3d : data (11.0, 19.0) = " << *data << endl;
else cout << "testBaseQuadTree3d : data (11.0, 19.0) = NULL" << endl;
}
int main(int argc, char** argv){
testBaseQuadTree();
testBaseQuadTree3d();
return 0;
}
project(Phoenix) project(Phoenix)
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 2.8)
file(GLOB_RECURSE graph_sources "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
add_library(phoenix_graph SHARED ${graph_sources})
install(TARGETS phoenix_graph LIBRARY DESTINATION ${LIBRARY_DIRECTORY} ARCHIVE DESTINATION ${LIBRARY_DIRECTORY})
file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h") file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
install(FILES ${headers} DESTINATION include/PhoenixGraph) install(FILES ${headers} DESTINATION include/PhoenixGraph)
project(Phoenix)
cmake_minimum_required(VERSION 2.8)
file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
install(FILES ${headers} DESTINATION include/PhoenixGraph/Tree)
/***************************************
Auteur : Pierre Aubert
Mail : aubertp7@gmail.com
Licence : CeCILL-C
****************************************/
#ifndef __PNTREELIGHT_H__
#define __PNTREELIGHT_H__
#include "PNTreeLightNode.h"
///@brief Describes only the PNTreeClass tree, without the size
template<typename T, typename U, unsigned char N>
class PNTreeLight{
public:
PNTreeLight();
PNTreeLight(T pos[N], T size[N], T sizeLimit = 1e-5);
virtual ~PNTreeLight();
PNTreeLight & operator = (const PNTreeLight<T,U,N> & other);
bool saveGnuplotData(const std::string & fileName);
bool saveGnuplotData(std::ofstream & fs, T height);
void setPosition(T pos[N]);
void setSize(T size[N]);
void setLimitSize(T limitSize);
bool addElement(T * posData, U * data);
const U * getLastData(T * posData) const;
const U * getCloserData(T * posData) const;
const U * getCloserDataDist(T & distFromCloserData, T * posData) const;
protected:
void copyPNTreeLight(const PNTreeLight<T,U,N> & other);
private:
PNTreeLight(const PNTreeLight<T,U,N> & other);
void initialisationPNTreeLight(T pos[N], T size[N], T sizeLimit);
///Position of the hyper cube
T p_pos[N];
///Size of the hyper cube
T p_size[N];
///Size limit of the cells
T p_sizeLimit;
///Table of the children of the current node
PNTreeLightNode<T,U,N> p_node;
};
#include "PNTreeLight_impl.h"
#endif
/***************************************
Auteur : Pierre Aubert
Mail : aubertp7@gmail.com
Licence : CeCILL-C
****************************************/
#include "PNTreeLightNode.h"
///Says is the neighbours search is finised
/** @param tabIsNeighbourChecked : tab of the neighbours search status (true if checked, false if not)
* @param nbNeighbour : number of neighbours in the table
* @return true if all the tabIsNeighbourChecked is true, false otherwise
*/
bool isNeighbourSearchFinised(const bool * tabIsNeighbourChecked, unsigned int nbNeighbour){
bool b(true);
for(unsigned int i(0u); i < nbNeighbour; ++i){
b &= tabIsNeighbourChecked[i];
}
return b;
}
/***************************************
Auteur : Pierre Aubert
Mail : aubertp7@gmail.com
Licence : CeCILL-C
****************************************/
#ifndef __PNTREE_LIGHT_NODE_H__
#define __PNTREE_LIGHT_NODE_H__
#include <iostream>
#include <fstream>
template<typename T, typename U, unsigned char N>
class PNTreeLightNode;
///@brief Describe a Quad tree
/** T : Type of the positions
* U : type of the data pointors to be stored
* N : number of dimensions of the N Tree
*/
template<typename T, typename U, unsigned char N>
class PNTreeLightNode{
public:
PNTreeLightNode();
virtual ~PNTreeLightNode();
bool addElement(T * posData, U * data, const T pos[N], const T size[N], const T sizeLimit);
void clear();
bool saveGnuplotData(const std::string & fileName, T pos[N], T size[N]);
bool saveGnuplotData(std::ofstream & fs, T height, T pos[N], T size[N]);
const U * getData() const;
U * getData();
const T * getDataPos() const;
T * getDataPos();
const U * getLastData(const T * posData, const T pos[N], const T size[N]) const;
bool getCloserData(U*& closerData, T & distFromCloserData, bool * tabIsNeighbourChecked, unsigned int nbNeighbour,
const T * posData, const T pos[N], const T size[N]) const;
const PNTreeLightNode<T, U, N> * getChildFromPos(T childPos[N], const T * posData, const T pos[N], const T size[N]) const;
PNTreeLightNode<T, U, N> * getChildFromPos(T childPos[N], const T * posData, const T pos[N], const T size[N]);
void getIndexOfChildFromPos(unsigned char index[N], const T posData[N], const T pos[N], const T size[N]) const;
void getIndexOfChildFromPos(unsigned char index[N], T posData[N], T pos[N], T size[N]);
unsigned char getFullIndexChild(unsigned char index[N]) const;
const PNTreeLightNode<T, U, N> * getTabChildren() const;
PNTreeLightNode<T, U, N> * getTabChildren();
const PNTreeLightNode<T, U, N> * getChild(unsigned char childId) const;
PNTreeLightNode<T, U, N> * getChild(unsigned char childId);
protected:
void copyPNTreeLightNode(const PNTreeLightNode<T, U, N> & other);
private:
PNTreeLightNode(const PNTreeLightNode<T, U, N> & other);
bool split(const T pos[N], const T size[N], T sizeLimit);
void initialisationPNTreeLightNode();
///Position of the data in the cell
T * p_posData;
///Data of the node
U * p_data;
///Position of the data in the hyper cube
PNTreeLightNode<T,U,N> * p_tableChildren;
};
bool isNeighbourSearchFinised(const bool * tabIsNeighbourChecked, unsigned int nbNeighbour);
#include "PNTreeLightNode_impl.h"
#endif
/***************************************
Auteur : Pierre Aubert
Mail : aubertp7@gmail.com
Licence : CeCILL-C
****************************************/
#ifndef __PNTREE_LIGHT_NODE_H_IMPL__
#define __PNTREE_LIGHT_NODE_H_IMPL__
#include <string.h>
#include <math.h>
#include "pstatic_computation.h"
#include "PNTreeLightNode.h"
///Default constructor of PNTreeLightNode
template<typename T, typename U, unsigned char N>
PNTreeLightNode<T, U, N>::PNTreeLightNode(){
initialisationPNTreeLightNode();
}
///Copy constructor of PNTreeLightNode
/** @param other : class to copy
*/
template<typename T, typename U, unsigned char N>
PNTreeLightNode<T, U, N>::PNTreeLightNode(const PNTreeLightNode<T, U, N> & other){
copyPNTreeLightNode(other);
}
///Destructeur of PNTreeLightNode
template<typename T, typename U, unsigned char N>
PNTreeLightNode<T, U, N>::~PNTreeLightNode(){
clear();
}
///Get the size of the child
/** @param[out] childSize : child size
* @param parentSize : parent size
*/
template<typename T, unsigned char N>
void makeHalfSize(T childSize[N], const T parentSize[N]){
for(unsigned char i(0lu); i < N; ++i){
childSize[i] = parentSize[i]/2.f;
}
}
///Check the size of the childs of a N Tree
/** @param halfSizeChild : table of half size of the current N Tree
* @param sizeLimit : limit of the cell size
* @return true if everything is OK, false if the childs are too small
*/
template<typename T, unsigned char N>
bool checkSizeLimitLight(const T halfSizeChild[N], T sizeLimit){
for(unsigned char i(0); i < N; ++i){
if(halfSizeChild[i] < sizeLimit) return false;
}
return true;
}
///Add an element in the PNTreeLightNode
/** @param posData : position of the data
* @param data : pointer to the data we want to sort
* @param pos : position of the current node
* @param size : size of the current node
* @param sizeLimit : limit of the cell size
* @return true on success, false otherwise
*/
template<typename T, typename U, unsigned char N>
bool PNTreeLightNode<T, U, N>::addElement(T * posData, U * data, const T pos[N], const T size[N], T sizeLimit){
if(!checkSizeLimitLight<T, N>(size, sizeLimit)){
return false;
}
if(p_tableChildren == NULL){
if(p_data == NULL){ //The cell is empty
p_data = data;
p_posData = posData;
return true;
}else{ //There is a data in the cell
if(!split(pos, size, sizeLimit)) return false;
return addElement(posData, data, pos, size, sizeLimit);
}
}else{ //There are children
T childPos[N];
PNTreeLightNode<T, U, N> * child = getChildFromPos(childPos, posData, pos, size);
if(child == NULL){
return false;
}else{
T childSize[N];
makeHalfSize<T,N>(childSize, size);
return child->addElement(posData, data, childPos, childSize, sizeLimit);
}
}
}
///Saves the PNTreeLightNode into a txt file for gnuplot
/** @param fileName : name of the text file we want to write
* @param pos : position of the current node
* @param size : size of the current node
* @return true on success, false otherwise
*/
template<typename T, typename U, unsigned char N>
bool PNTreeLightNode<T, U, N>::saveGnuplotData(const std::string & fileName, T pos[N], T size[N]){
if(fileName == "") return false;
std::ofstream fs;
fs.open(fileName);
if(!fs.is_open()){return false;}
bool b = saveGnuplotData(fs, 0, pos, size);
fs.close();
return b;
}
///Saves the PNTreeLightNode into a txt file for gnuplot
/** @param fs : text file we want to write
* @param height : height of the quad to draw
* @param pos : position of the current node
* @param size : size of the current node
* @return true on success, false otherwise
*/
template<typename T, typename U, unsigned char N>
bool PNTreeLightNode<T, U, N>::saveGnuplotData(std::ofstream & fs, T height, T pos[N], T size[N]){
if(N == 2){
fs << pos[0] << "\t" << pos[1] << "\t" << height << std::endl;
fs << (pos[0] + size[0]) << "\t" << pos[1] << "\t" << height << std::endl;
fs << (pos[0] + size[0]) << "\t" << (pos[1] + size[1]) << "\t" << height << std::endl;
fs << pos[0] << "\t" << (pos[1] + size[1]) << "\t" << height << std::endl;
fs << pos[0] << "\t" << pos[1] << "\t" << height << std::endl;
}else if(N == 3){
T px0(pos[0]), px1(pos[0] + size[0]);
T py0(pos[1]), py1(pos[1] + size[1]);
T pz0(pos[2]), pz1(pos[2] + size[2]);
//lower quad
fs << px0 << "\t" << py0 << "\t" << pz0 << std::endl;
fs << px1 << "\t" << py0 << "\t" << pz0 << std::endl;
fs << px1 << "\t" << py1 << "\t" << pz0 << std::endl;
fs << px0 << "\t" << py1 << "\t" << pz0 << std::endl;
fs << px0 << "\t" << py0 << "\t" << pz0 << std::endl;
fs << std::endl;
//upper quad
fs << px0 << "\t" << py0 << "\t" << pz1 << std::endl;
fs << px1 << "\t" << py0 << "\t" << pz1 << std::endl;
fs << px1 << "\t" << py1 << "\t" << pz1 << std::endl;
fs << px0 << "\t" << py1 << "\t" << pz1 << std::endl;
fs << px0 << "\t" << py0 << "\t" << pz1 << std::endl;
fs << std::endl;
//Lines on Oz axis
fs << px0 << "\t" << py0 << "\t" << pz0 << std::endl;
fs << px0 << "\t" << py0 << "\t" << pz1 << std::endl;
fs << std::endl;
fs << px0 << "\t" << py1 << "\t" << pz0 << std::endl;
fs << px0 << "\t" << py1 << "\t" << pz1 << std::endl;
fs << std::endl;
fs << px1 << "\t" << py1 << "\t" << pz0 << std::endl;
fs << px1 << "\t" << py1 << "\t" << pz1 << std::endl;
fs << std::endl;
fs << px1 << "\t" << py0 << "\t" << pz0 << std::endl;
fs << px1 << "\t" << py0 << "\t" << pz1 << std::endl;
}
fs << std::endl;
if(p_tableChildren != NULL){
T childSize[N], posChild[N];
makeHalfSize<T,N>(childSize, size);
for(unsigned char i(0); i < PPower<2, N>::Value; ++i){
for(unsigned char k(0); k < N; ++k){
posChild[k] = pos[k] + ((i >> k) & 1)*childSize[k];
}
p_tableChildren[i].saveGnuplotData(fs, height + 1, posChild, childSize);
}
}
return true;
}
///Clear the PNTreeLightNode content
template<typename T, typename U, unsigned char N>
void PNTreeLightNode<T, U, N>::clear(){
if(p_tableChildren != NULL){
for(unsigned char i(0); i < PPower<2, N>::Value; ++i){
PNTreeLightNode<T, U, N> * child = &(p_tableChildren[i]);
child->clear();
}