Skip to content

Commit

Permalink
Readme update
Browse files Browse the repository at this point in the history
  • Loading branch information
attcs committed Feb 17, 2024
1 parent 67a9bf6 commit 0230b94
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 89 deletions.
107 changes: 65 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,13 @@ Usage of Container types
auto constexpr points = array{ Point3D{0,0,0}, Point3D{1,1,1}, Point3D{2,2,2} };
auto const octree = OctreePointC(points, 3 /*max depth*/);

auto const search_box = BoundingBox3D{ {0.5, 0.5, 0.5}, {2.5, 2.5, 2.5} };
auto ids = octree.RangeSearch(search_box); // -> { 1, 2 }
auto knn_ids = octree.GetNearestNeighbors(Point3D{ 1.1,1.1,1.1 }, 2 /*k*/); // -> { 1, 2 }
auto const searchBox = BoundingBox3D{ {0.5, 0.5, 0.5}, {2.5, 2.5, 2.5} };
auto const pointIDs = octree.RangeSearch(searchBox); //: { 1, 2 }

auto neighborNo = 2;
auto pointIDsByKNN = octree.GetNearestNeighbors(Point3D{ 1.1, 1.1, 1.1 }
, neighborNo
); //: { 1, 2 }
}

// Example #2: Quadtree for bounding boxes
Expand All @@ -134,39 +138,49 @@ Usage of Container types
BoundingBox2D{ { 1.2, 1.2 }, { 2.8, 2.8 } }
};

auto quadtreebox = QuadtreeBoxC(boxes, 3
, std::nullopt // user-provided bounding box for all
auto quadtree = QuadtreeBoxC(boxes
, 3 // max depth
, std::nullopt // user-provided bounding Box for all
, 2 // max element in a node
, false // parallel calculation flag
, false // parallel calculation option
);

// Collision detection
auto ids_pairs_colliding = quadtreebox.CollisionDetection(); // { {1,4}, {2,4} }
auto collidingIDPairs = quadtree.CollisionDetection(); //: { {1,4}, {2,4} }

auto searchBox = BoundingBox2D{ { 1.0, 1.0 }, { 3.1, 3.1 } };

// Boxes within the range
auto insideBoxIDs = quadtree.RangeSearch(searchBox); //: { 1, 2, 4 }

// Range search
auto search_box = BoundingBox2D{ { 1.0, 1.0 }, { 3.1, 3.1 } };
auto ids_inside = quadtreebox.RangeSearch(search_box); // -> { 1, 2, 4 }
auto ids_overlaping = quadtreebox.RangeSearch<false /*overlap is enough*/>(search_box);
// -> { 1, 2, 3, 4 }
// Overlapping Boxes with the range
constexpr bool shouldFullyContain = false; // overlap is enough
auto overlappingBoxIDs = quadtree.RangeSearch<shouldFullyContain>(searchBox);
//: { 1, 2, 3, 4 }

// Picked boxes
auto ptPick = Point2D{ 2.5, 2.5 };
auto ids_picked = quadtreebox.PickSearch(ptPick); // -> { 2, 4 }
auto pickPoint = Point2D{ 2.5, 2.5 };
auto pickedIDs = quadtree.PickSearch(pickPoint); //: { 2, 4 }
}

// Example #3: Parallel creation of octree for bounding boxes
{
auto boxes = vector{ BoundingBox3D{ { 0.0, 0.0, 0.0 }, { 1.0, 1.0, 1.0 } } /* and more... */ };
// Using ctor
{
auto octreebox = OctreeBoxC(boxes, 3, std::nullopt, OctreeBox::max_element_default
, true // Set std::execution::parallel_unsequenced_policy
);
}
// Using Create
{
auto octreebox = OctreeBoxC::Create<std::execution::parallel_unsequenced_policy>(boxes, 3);
}
auto boxes = vector
{
BoundingBox3D{ { 0.0, 0.0, 0.0 }, { 1.0, 1.0, 1.0 } }
/* and more... */
};

auto octreeUsingCtor = OctreeBoxC(boxes
, 3
, std::nullopt
, OctreeBox::max_element_default
, true // Set std::execution::parallel_unsequenced_policy
);

using namespace std::execution;
auto octreeUsingCreate = OctreeBoxC::Create<parallel_unsequenced_policy>(boxes
, 3
);
}
```
Expand All @@ -179,10 +193,13 @@ Usage of Core types
{
auto constexpr points = array{ Point3D{0,0,0}, Point3D{1,1,1}, Point3D{2,2,2} };
auto const octree = OctreePoint(points, 3 /*max depth*/);
auto const search_box = BoundingBox3D{ {0.5, 0.5, 0.5}, {2.5, 2.5, 2.5} };
auto ids = octree.RangeSearch(search_box, points); // -> { 1, 2 }
auto knn_ids = octree.GetNearestNeighbors(Point3D{ 1.1,1.1,1.1 }, 2 /*k*/, points); // -> { 1, 2 }
auto const searchBox = BoundingBox3D{ {0.5, 0.5, 0.5}, {2.5, 2.5, 2.5} };
auto pointIDsByRange = octree.RangeSearch(searchBox, points); //: { 1, 2 }
auto pointIDsByKNN = octree.GetNearestNeighbors(Point3D{ 1.1,1.1,1.1 }
, 2 // k neighbor
, points
); //: { 1, 2 }
}
// Example #2: Quadtree for bounding boxes
Expand All @@ -196,23 +213,29 @@ Usage of Core types
BoundingBox2D{ { 1.2, 1.2 }, { 2.8, 2.8 } }
};
auto quadtreebox = QuadtreeBox(boxes, 3
, std::nullopt // user-provided bounding box for all
auto qt = QuadtreeBox(boxes
, 3 // max depth
, std::nullopt // user-provided bounding Box for all
, 2 // max element in a node
);
// Collision detection
auto ids_pairs_colliding = quadtreebox.CollisionDetection(boxes); // { {1,4}, {2,4} }
auto collidingIDPairs = qt.CollisionDetection(boxes); //: { {1,4}, {2,4} }
auto searchBox = BoundingBox2D{ { 1.0, 1.0 }, { 3.1, 3.1 } };
// Boxes within the range
auto insideBoxIDs = qt.RangeSearch(searchBox, boxes); //: { 1, 2, 4 }
// Overlapping Boxes with the range
constexpr bool shouldFullyContain = false;
auto overlappingBoxIDs = qt.RangeSearch<shouldFullyContain>(searchBox
, boxes
); //: { 1, 2, 3, 4 }
// Range search
auto search_box = BoundingBox2D{ { 1.0, 1.0 }, { 3.1, 3.1 } };
auto ids_inside = quadtreebox.RangeSearch(search_box, boxes); // -> { 1, 2, 4 }
auto ids_overlaping = quadtreebox.RangeSearch<false/*overlap is enough*/>(search_box, boxes);
// -> { 1, 2, 3, 4 }
// Picked boxes
auto ptPick = Point2D{ 2.5, 2.5 };
auto ids_picked = quadtreebox.PickSearch(ptPick, boxes); // -> { 2, 4 }
auto pickPoint = Point2D{ 2.5, 2.5 };
auto pickedBoxIDs = qt.PickSearch(pickPoint, boxes); //: { 2, 4 }
}
```

Expand Down
Binary file modified docs/quadtree_example.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
103 changes: 56 additions & 47 deletions unittests/example.tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,51 +14,55 @@ namespace Example
auto constexpr points = array{ Point3D{0,0,0}, Point3D{1,1,1}, Point3D{2,2,2} };
auto const octree = OctreePoint(points, 3 /*max depth*/);

auto const search_box = BoundingBox3D{ {0.5, 0.5, 0.5}, {2.5, 2.5, 2.5} };
auto ids = octree.RangeSearch(search_box, points); // -> { 1, 2 }
auto knn_ids = octree.GetNearestNeighbors(Point3D{ 1.1,1.1,1.1 }, 2 /*k*/, points); // -> { 1, 2 }


Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2}, ids));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2}, knn_ids));
auto const searchBox = BoundingBox3D{ {0.5, 0.5, 0.5}, {2.5, 2.5, 2.5} };
auto pointIDsByRange = octree.RangeSearch(searchBox, points); //: { 1, 2 }
auto pointIDsByKNN = octree.GetNearestNeighbors(Point3D{ 1.1,1.1,1.1 }
, 2 // neighborNo
, points
); //: { 1, 2 }

Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2}, pointIDsByRange));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2}, pointIDsByKNN));
}


TEST_METHOD(Example2)
{
auto boxes = vector
{
BoundingBox2D{ { 0.0, 0.0 }, { 1.0, 1.0 } },
BoundingBox2D{ { 1.0, 1.0 }, { 2.0, 2.0 } },
BoundingBox2D{ { 2.0, 2.0 }, { 3.0, 3.0 } },
BoundingBox2D{ { 3.0, 3.0 }, { 4.0, 4.0 } },
BoundingBox2D{ { 1.2, 1.2 }, { 2.8, 2.8 } }
BoundingBox2D{ { 0.0, 0.0 }, { 1.0, 1.0 } },
BoundingBox2D{ { 1.0, 1.0 }, { 2.0, 2.0 } },
BoundingBox2D{ { 2.0, 2.0 }, { 3.0, 3.0 } },
BoundingBox2D{ { 3.0, 3.0 }, { 4.0, 4.0 } },
BoundingBox2D{ { 1.2, 1.2 }, { 2.8, 2.8 } }
};

auto quadtreebox = QuadtreeBox(boxes, 3
auto qt = QuadtreeBox(boxes
, 3 // max depth
, std::nullopt // user-provided bounding Box for all
, 2 // max element in a node
);

auto idPairColliding = quadtreebox.CollisionDetection(boxes); // { {1,4}, {2,4} }
auto collidingIDPairs = qt.CollisionDetection(boxes); //: { {1,4}, {2,4} }

auto search_box = BoundingBox2D{ { 1.0, 1.0 }, { 3.1, 3.1 } };
auto searchBox = BoundingBox2D{ { 1.0, 1.0 }, { 3.1, 3.1 } };

// Boxes within the range
auto ids_inside = quadtreebox.RangeSearch(search_box, boxes); // -> { 1, 2, 4 }
auto insideBoxIDs = qt.RangeSearch(searchBox, boxes); //: { 1, 2, 4 }

// Overlapping Boxes with the range
auto ids_overlaping = quadtreebox.RangeSearch<false /*overlap is enough*/>(search_box, boxes); // -> { 1, 2, 3, 4 }
constexpr bool shouldFullyContain = false;
auto overlappingBoxIDs = qt.RangeSearch<shouldFullyContain>(searchBox, boxes); //: { 1, 2, 3, 4 }

// Picked boxes
auto ptPick = Point2D{ 2.5, 2.5 };
auto ids_picked = quadtreebox.PickSearch(ptPick, boxes); // -> { 2, 4 }
auto pickPoint = Point2D{ 2.5, 2.5 };
auto pickedBoxIDs = qt.PickSearch(pickPoint, boxes); //: { 2, 4 }


Assert::IsTrue(std::ranges::is_permutation(vector<std::pair<entity_id_type, entity_id_type>>{ {1, 4}, { 2, 4 } }, idPairColliding));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2, 4}, ids_inside));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2, 3, 4}, ids_overlaping));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{2, 4}, ids_picked));
Assert::IsTrue(std::ranges::is_permutation(vector<std::pair<entity_id_type, entity_id_type>>{ {1, 4}, { 2, 4 } }, collidingIDPairs));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2, 4}, insideBoxIDs));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2, 3, 4}, overlappingBoxIDs));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{2, 4}, pickedBoxIDs));
}


Expand All @@ -77,51 +81,56 @@ namespace Example
auto constexpr points = array{ Point3D{0,0,0}, Point3D{1,1,1}, Point3D{2,2,2} };
auto const octree = OctreePointC(points, 3 /*max depth*/);

auto const search_box = BoundingBox3D{ {0.5, 0.5, 0.5}, {2.5, 2.5, 2.5} };
auto ids = octree.RangeSearch(search_box); // -> { 1, 2 }
auto knn_ids = octree.GetNearestNeighbors(Point3D{ 1.1,1.1,1.1 }, 2 /*k*/); // -> { 1, 2 }
auto const searchBox = BoundingBox3D{ {0.5, 0.5, 0.5}, {2.5, 2.5, 2.5} };
auto const pointIDs = octree.RangeSearch(searchBox); //: { 1, 2 }

auto neighborNo = 2;
auto pointIDsByKNN = octree.GetNearestNeighbors(Point3D{ 1.1, 1.1, 1.1 }
, neighborNo
); //: { 1, 2 }

Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2}, ids));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2}, knn_ids));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2}, pointIDs));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2}, pointIDsByKNN));
}


TEST_METHOD(Example2_Container)
{
auto boxes = vector
{
BoundingBox2D{ { 0.0, 0.0 }, { 1.0, 1.0 } },
BoundingBox2D{ { 1.0, 1.0 }, { 2.0, 2.0 } },
BoundingBox2D{ { 2.0, 2.0 }, { 3.0, 3.0 } },
BoundingBox2D{ { 3.0, 3.0 }, { 4.0, 4.0 } },
BoundingBox2D{ { 1.2, 1.2 }, { 2.8, 2.8 } }
BoundingBox2D{ { 0.0, 0.0 }, { 1.0, 1.0 } },
BoundingBox2D{ { 1.0, 1.0 }, { 2.0, 2.0 } },
BoundingBox2D{ { 2.0, 2.0 }, { 3.0, 3.0 } },
BoundingBox2D{ { 3.0, 3.0 }, { 4.0, 4.0 } },
BoundingBox2D{ { 1.2, 1.2 }, { 2.8, 2.8 } }
};

auto quadtreebox = QuadtreeBoxC(boxes, 3
auto quadtree = QuadtreeBoxC(boxes
, 3 // max depth
, std::nullopt // user-provided bounding Box for all
, 2 // max element in a node
, false // parallel calculation flag
, false // parallel calculation option
);

auto idPairColliding = quadtreebox.CollisionDetection(); // { {1,4}, {2,4} }
auto collidingIDPairs = quadtree.CollisionDetection(); //: { {1,4}, {2,4} }

auto search_box = BoundingBox2D{ { 1.0, 1.0 }, { 3.1, 3.1 } };
auto searchBox = BoundingBox2D{ { 1.0, 1.0 }, { 3.1, 3.1 } };

// Boxes within the range
auto ids_inside = quadtreebox.RangeSearch(search_box); // -> { 1, 2, 4 }
auto insideBoxIDs = quadtree.RangeSearch(searchBox); //: { 1, 2, 4 }

// Overlapping Boxes with the range
auto ids_overlaping = quadtreebox.RangeSearch<false /*overlap is enough*/>(search_box); // -> { 1, 2, 3, 4 }
constexpr bool shouldFullyContain = false; // overlap is enough
auto overlappingBoxIDs = quadtree.RangeSearch<shouldFullyContain>(searchBox); //: { 1, 2, 3, 4 }

// Picked boxes
auto ptPick = Point2D{ 2.5, 2.5 };
auto ids_picked = quadtreebox.PickSearch(ptPick); // -> { 2, 4 }
auto pickPoint = Point2D{ 2.5, 2.5 };
auto pickedIDs = quadtree.PickSearch(pickPoint); //: { 2, 4 }

Assert::IsTrue(std::ranges::is_permutation(vector<std::pair<entity_id_type, entity_id_type>>{ {1, 4}, { 2, 4 } }, idPairColliding));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2, 4}, ids_inside));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2, 3, 4}, ids_overlaping));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{2, 4}, ids_picked));
Assert::IsTrue(std::ranges::is_permutation(vector<std::pair<entity_id_type, entity_id_type>>{ {1, 4}, { 2, 4 } }, collidingIDPairs));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2, 4}, insideBoxIDs));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{1, 2, 3, 4}, overlappingBoxIDs));
Assert::IsTrue(std::ranges::is_permutation(vector<entity_id_type>{2, 4}, pickedIDs));
}


Expand All @@ -130,13 +139,13 @@ namespace Example
auto boxes = vector{ BoundingBox3D{ { 0.0, 0.0, 0.0 }, { 1.0, 1.0, 1.0 } } /* and more... */ };
// Using ctor
{
auto octreebox = OctreeBoxC(boxes, 3, std::nullopt, OctreeBox::DEFAULT_MAX_ELEMENT
auto octreeBox = OctreeBoxC(boxes, 3, std::nullopt, OctreeBox::DEFAULT_MAX_ELEMENT
, true // Set std::execution::parallel_unsequenced_policy
);
}
// Using Create
{
auto octreebox = OctreeBoxC::Create<std::execution::parallel_unsequenced_policy>(boxes, 3);
auto octreeBox = OctreeBoxC::Create<std::execution::parallel_unsequenced_policy>(boxes, 3);
}
// or
// TreeBoxND<3>::template Create<std::execution::parallel_unsequenced_policy>(boxes, 3);
Expand Down

0 comments on commit 0230b94

Please sign in to comment.