From d82f97ba0855c00d5c10b3cd1f677d5324b80222 Mon Sep 17 00:00:00 2001 From: Christopher Liem Date: Thu, 23 Jan 2025 10:33:04 -0500 Subject: [PATCH 01/10] Debug-C Build CMake --- src/CMakeSettings.json | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/CMakeSettings.json b/src/CMakeSettings.json index 84067b45c..a9bb8e4af 100644 --- a/src/CMakeSettings.json +++ b/src/CMakeSettings.json @@ -175,6 +175,39 @@ "type": "BOOL" } ] + }, + { + "name": "x64-Debug-C", + "generator": "Visual Studio 17 2022 Win64", + "configurationType": "Debug", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_x64_x64" ], + "variables": [ + { + "name": "DHARTAPI_Config", + "value": "All", + "type": "STRING" + }, + { + "name": "DHARTAPI_EnableTests", + "value": "True", + "type": "BOOL" + }, + { + "name": "DHARTAPI_BuildCSharpTests", + "value": "False", + "type": "BOOL" + }, + { + "name": "DHARTAPI_EnableCSharp", + "value": "False", + "type": "BOOL" + } + ] } ] } \ No newline at end of file From c822ae3b61cd1dc49e8dbfeae781ad991c2aeacf Mon Sep 17 00:00:00 2001 From: Christopher Liem Date: Thu, 23 Jan 2025 10:54:10 -0500 Subject: [PATCH 02/10] Add & query step types in graph (cpp) --- src/Cpp/analysismethods/src/graph_generator.h | 21 +++++ src/Cpp/analysismethods/src/graph_utils.cpp | 77 ++++++++++++++++++ src/Cpp/tests/src/GraphGenerator.cpp | 79 +++++++++++++++++++ 3 files changed, 177 insertions(+) diff --git a/src/Cpp/analysismethods/src/graph_generator.h b/src/Cpp/analysismethods/src/graph_generator.h index 6f21861e2..cf3adbc37 100644 --- a/src/Cpp/analysismethods/src/graph_generator.h +++ b/src/Cpp/analysismethods/src/graph_generator.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,8 @@ namespace HF::SpatialStructures { class Graph; struct Edge; enum STEP; + struct Subgraph; + struct EdgeSet; } /*! \brief Generate a graph of accessible space from a given start point. @@ -782,6 +785,24 @@ namespace HF::GraphGenerator { const GraphParams & params ); + HF::SpatialStructures::EdgeSet CalculateStepType( + const HF::SpatialStructures::Subgraph& sg, + RayTracer& rt, + const GraphParams& params + ); + + std::vector CalculateStepType( + const HF::SpatialStructures::Graph& g, + RayTracer& rt, + const GraphParams& params + ); + + void CalculateAndStoreStepType( + HF::SpatialStructures::Graph& g, + RayTracer& rt, + const GraphParams& params + ); + /*! \brief Determine if there is a valid line of sight between parent and child diff --git a/src/Cpp/analysismethods/src/graph_utils.cpp b/src/Cpp/analysismethods/src/graph_utils.cpp index c4b362891..0c41ff0cf 100644 --- a/src/Cpp/analysismethods/src/graph_utils.cpp +++ b/src/Cpp/analysismethods/src/graph_utils.cpp @@ -300,6 +300,83 @@ namespace HF::GraphGenerator { return calc_slope > -1.0 * gp.down_slope && calc_slope < gp.up_slope; } + HF::SpatialStructures::EdgeSet CalculateStepType(const HF::SpatialStructures::Subgraph& sg, RayTracer& rt, const GraphParams& params) { + // Step type will be stored here and returned from this function + + //Initialize output + std::vector edge_set; + + //From Subgraph sg + Node parent_node = sg.m_parent; + std::vector edge_list = sg.m_edges; + + // We can preallocate this container to have edge_list.size() + // blocks since we know how many children are in the subgraph. + std::vector children(edge_list.size()); + auto it_children = children.begin(); + + //For every edge... + for (Edge link_a : edge_list) { + Node curr_child = link_a.child; + + //Type Casting + real_t parent_x = CastToReal(parent_node.x); + real_t parent_y = CastToReal(parent_node.y); + real_t parent_z = CastToReal(parent_node.z); + + real_t child_x = CastToReal(curr_child.x); + real_t child_y = CastToReal(curr_child.y); + real_t child_z = CastToReal(curr_child.z); + + std::vector parent_loc = { parent_x, parent_y, parent_z }; + std::vector child_loc = { child_x, child_y, child_z }; + + real3 parent_cast = CastToReal3(parent_loc); + real3 child_cast = CastToReal3(child_loc); + + //Get the step type between parent and child + STEP step_type = CheckConnection(parent_cast, child_cast, rt, params); + + //Construct an intedge for this parent-child pair to add to edgeset + HF::SpatialStructures::IntEdge ie = { link_a.child.id, static_cast(step_type) }; + + *(it_children++) = ie; + } + + HF::SpatialStructures::EdgeSet es = { parent_node.id, children }; + + return es; + } + + std::vector CalculateStepType(const HF::SpatialStructures::Graph& g, RayTracer& rt, const GraphParams& params) { + // Retrieve all nodes from g so we can obtain subgraphs. + std::vector nodes = g.Nodes(); + + // The result container will always be, at most, the node count of g. + // We can preallocate this memory so we do not have to resize during the loop below. + std::vector result(nodes.size()); + auto it_result = result.begin(); + + for (Node parent_node : nodes) { + // Get subgraph via parent_node + HF::SpatialStructures::Subgraph sg = g.GetSubgraph(parent_node); + + // Call CalculateStepType using the subgraph + HF::SpatialStructures::EdgeSet step_types = CalculateStepType(sg, rt, params); + + *(it_result++) = step_types; + } + return result; + } + + void CalculateAndStoreStepType(HF::SpatialStructures::Graph& g, RayTracer& rt, const GraphParams& params) { + // calculates and stores step types of all edges and stores it in the hashmap + + // Get vector of edgesets which contain step types + auto result = HF::GraphGenerator::CalculateStepType(g, rt, params); + g.AddEdges(result, "step_type"); + } + HF::SpatialStructures::STEP CheckConnection( const real3& parent, const real3& child, diff --git a/src/Cpp/tests/src/GraphGenerator.cpp b/src/Cpp/tests/src/GraphGenerator.cpp index 9fd182339..7a8226dc3 100644 --- a/src/Cpp/tests/src/GraphGenerator.cpp +++ b/src/Cpp/tests/src/GraphGenerator.cpp @@ -663,5 +663,84 @@ TEST(_GraphGenerator, OcclusionCheck) { ASSERT_FALSE(occlusion_check_child_2); } +TEST(_GraphGenerator, CalculateStepType) { + EmbreeRayTracer ray_tracer = CreateGGExmapleRT(); + //! [EX_CheckStepTypes] + + // Create graph parameters + HF::GraphGenerator::GraphParams params; + params.up_step = 2; params.down_step = 2; + params.up_slope = 45; params.down_slope = 45; + params.precision.node_z = 0.01f; + params.precision.ground_offset = 0.01f; + + Graph g; + Node N0 = Node(0, 0, 1); + Node N1 = Node(0, 2, 0); + Node N2 = Node(1, 0, 0); + Node N3 = Node(0, 1, 0); + Node N4 = Node(2, 0, 0); + + g.addEdge(N0, N1); + g.addEdge(N0, N2); + g.addEdge(N0, N3); + g.addEdge(N0, N4); + + g.Compress(); + + std::vector step_types = HF::GraphGenerator::CalculateStepType(g, HF::RayTracer::MultiRT(&ray_tracer), params); + + HF::SpatialStructures::EdgeSet node_one_edgeset = step_types[0]; + std::vector node_one_inteedges = node_one_edgeset.children; + + std::vector expected_step_types = { 1,0,0,1 }; + + for (int i = 0; i < expected_step_types.size(); i++) { + float step_type = node_one_inteedges[i].weight; + ASSERT_EQ(step_type, expected_step_types[i]); + } + //! [EX_CheckStepTypes] +} + +TEST(_GraphGenerator, CalculateAndStoreStepType) { + EmbreeRayTracer ray_tracer = CreateGGExmapleRT(); + //! [EX_CheckStepTypes] + + // Create graph parameters + HF::GraphGenerator::GraphParams params; + params.up_step = 2; params.down_step = 2; + params.up_slope = 45; params.down_slope = 45; + params.precision.node_z = 0.01f; + params.precision.ground_offset = 0.01f; + + Graph g; + Node N0 = Node(0, 0, 1); + Node N1 = Node(0, 2, 0); + Node N2 = Node(1, 0, 0); + Node N3 = Node(0, 1, 0); + Node N4 = Node(2, 0, 0); + + g.addEdge(N0, N1); + g.addEdge(N0, N2); + g.addEdge(N0, N3); + g.addEdge(N0, N4); + + g.Compress(); + + CalculateAndStoreStepType(g, HF::RayTracer::MultiRT(&ray_tracer), params); + + std::vector result = g.GetEdges("step_type"); + + HF::SpatialStructures::EdgeSet node_one_edgeset = result[0]; + std::vector node_one_inteedges = node_one_edgeset.children; + + std::vector expected_step_types = { 1,0,0,1 }; + + for (int i = 0; i < expected_step_types.size(); i++) { + float step_type = node_one_inteedges[i].weight; + ASSERT_EQ(step_type, expected_step_types[i]); + } + +} From 3e73169e1ceb67d6db70513b5e2d4c33d9dcd4d3 Mon Sep 17 00:00:00 2001 From: Christopher Liem Date: Thu, 23 Jan 2025 13:17:52 -0500 Subject: [PATCH 03/10] Query Step Type C_Interface --- src/Cinterface/analysis_C.cpp | 28 ++++++++++ src/Cinterface/analysis_C.h | 39 ++++++++++++++ src/Cpp/analysismethods/src/graph_generator.h | 6 +-- src/Cpp/analysismethods/src/graph_utils.cpp | 12 +++-- src/Cpp/tests/src/GraphAlgorithms.cpp | 1 - src/Cpp/tests/src/GraphGenerator.cpp | 53 +++++++++++++++++-- .../dhart/graphgenerator/graph_generator.py | 24 +++++++++ .../graph_generator_native_functions.py | 30 ++++++++++- .../graphgenerator/test_GraphGenerator.py | 33 +++++++++++- 9 files changed, 210 insertions(+), 16 deletions(-) diff --git a/src/Cinterface/analysis_C.cpp b/src/Cinterface/analysis_C.cpp index b7ea32b28..28f1fe167 100644 --- a/src/Cinterface/analysis_C.cpp +++ b/src/Cinterface/analysis_C.cpp @@ -105,3 +105,31 @@ C_INTERFACE GenerateGraphObstacles( *out_graph = G; return OK; } + +C_INTERFACE CalculateAndStoreStepTypes( + HF::SpatialStructures::Graph* g, + HF::RayTracer::EmbreeRayTracer* ray_tracer, + float up_step, + float down_step, + float up_slope, + float down_slope, + float ground_offset, + float node_z, + float node_spacing + ) { + HF::GraphGenerator::Precision precision = { node_z, node_spacing, ground_offset }; + HF::GraphGenerator::GraphParams params; + + //Setup params struct + params.up_step = up_step; params.down_step = down_step; + params.up_slope = up_slope; params.down_slope = down_slope; + params.precision.ground_offset = ground_offset; + params.precision.node_z = node_z; + params.precision.node_spacing = node_spacing; + + auto result = CalculateStepType(*g, HF::RayTracer::MultiRT(ray_tracer), params); + + g->AddEdges(result, "step_type"); + + return OK; +} diff --git a/src/Cinterface/analysis_C.h b/src/Cinterface/analysis_C.h index ae11cbe91..75cb177df 100644 --- a/src/Cinterface/analysis_C.h +++ b/src/Cinterface/analysis_C.h @@ -223,6 +223,45 @@ C_INTERFACE GenerateGraphObstacles( HF::SpatialStructures::Graph** out_graph ); +/*! + \brief Query the graph and identify the step types of all edges, adding them to the graph. + + \param g Graph used to query step types. + + \param ray_tracer Raytracer containing the geometry to use for graph generation. + + \param up_step Maximum height of a step the graph can traverse. + Any steps higher this will be considered inaccessible. + + \param up_slope Maximum upward slope the graph can traverse in degrees. + Any slopes steeper than this will be considered inaccessible. + + \param down_step Maximum step down the graph can traverse. + Any steps steeper than this will be considered inaccessible. + + \param down_slope The maximum downward slope the graph can traverse. + Any slopes steeper than this will be considered inaccessible. + + \param ground_offset Distance to offset nodes from the ground before checking line of sight. + + \param node_z Precision to round the z-component of nodes after a raycast is performed. + + \param node_spacing Precision to round nodes after spacing is calculated. + + \returns \link HF_STATUS::OK \endlink if query was successful and edges corresponding to step types have been added to the graph. +*/ + +C_INTERFACE CalculateAndStoreStepTypes( + HF::SpatialStructures::Graph* g, + HF::RayTracer::EmbreeRayTracer* ray_tracer, + float up_step, + float down_step, + float up_slope, + float down_slope, + float ground_offset, + float node_z, + float node_spacing +); /**@}*/ #endif /* ANALYSIS_C_H */ diff --git a/src/Cpp/analysismethods/src/graph_generator.h b/src/Cpp/analysismethods/src/graph_generator.h index cf3adbc37..d13d6bb62 100644 --- a/src/Cpp/analysismethods/src/graph_generator.h +++ b/src/Cpp/analysismethods/src/graph_generator.h @@ -787,19 +787,19 @@ namespace HF::GraphGenerator { HF::SpatialStructures::EdgeSet CalculateStepType( const HF::SpatialStructures::Subgraph& sg, - RayTracer& rt, + HF::RayTracer::MultiRT& rt, const GraphParams& params ); std::vector CalculateStepType( const HF::SpatialStructures::Graph& g, - RayTracer& rt, + HF::RayTracer::MultiRT& rt, const GraphParams& params ); void CalculateAndStoreStepType( HF::SpatialStructures::Graph& g, - RayTracer& rt, + HF::RayTracer::MultiRT& rt, const GraphParams& params ); diff --git a/src/Cpp/analysismethods/src/graph_utils.cpp b/src/Cpp/analysismethods/src/graph_utils.cpp index 0c41ff0cf..631ed6160 100644 --- a/src/Cpp/analysismethods/src/graph_utils.cpp +++ b/src/Cpp/analysismethods/src/graph_utils.cpp @@ -300,7 +300,7 @@ namespace HF::GraphGenerator { return calc_slope > -1.0 * gp.down_slope && calc_slope < gp.up_slope; } - HF::SpatialStructures::EdgeSet CalculateStepType(const HF::SpatialStructures::Subgraph& sg, RayTracer& rt, const GraphParams& params) { + HF::SpatialStructures::EdgeSet CalculateStepType(const HF::SpatialStructures::Subgraph& sg, HF::RayTracer::MultiRT& rt, const GraphParams& params) { // Step type will be stored here and returned from this function //Initialize output @@ -348,7 +348,7 @@ namespace HF::GraphGenerator { return es; } - std::vector CalculateStepType(const HF::SpatialStructures::Graph& g, RayTracer& rt, const GraphParams& params) { + std::vector CalculateStepType(const HF::SpatialStructures::Graph& g, HF::RayTracer::MultiRT& rt, const GraphParams& params) { // Retrieve all nodes from g so we can obtain subgraphs. std::vector nodes = g.Nodes(); @@ -369,11 +369,13 @@ namespace HF::GraphGenerator { return result; } - void CalculateAndStoreStepType(HF::SpatialStructures::Graph& g, RayTracer& rt, const GraphParams& params) { - // calculates and stores step types of all edges and stores it in the hashmap + void CalculateAndStoreStepType(HF::SpatialStructures::Graph& g, HF::RayTracer::MultiRT& rt, const GraphParams& params) { + // calculates and stores step types of all edges and stores it in the graph - // Get vector of edgesets which contain step types + // Get all edges with weights corresponding to step type auto result = HF::GraphGenerator::CalculateStepType(g, rt, params); + + // Add edges to the graph g.AddEdges(result, "step_type"); } diff --git a/src/Cpp/tests/src/GraphAlgorithms.cpp b/src/Cpp/tests/src/GraphAlgorithms.cpp index f8f47fe53..41a17be77 100644 --- a/src/Cpp/tests/src/GraphAlgorithms.cpp +++ b/src/Cpp/tests/src/GraphAlgorithms.cpp @@ -12,7 +12,6 @@ #include #include "analysis_C.h" -#include "graph.h" namespace HF { diff --git a/src/Cpp/tests/src/GraphGenerator.cpp b/src/Cpp/tests/src/GraphGenerator.cpp index 7a8226dc3..06a753b1e 100644 --- a/src/Cpp/tests/src/GraphGenerator.cpp +++ b/src/Cpp/tests/src/GraphGenerator.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -704,7 +705,6 @@ TEST(_GraphGenerator, CalculateStepType) { TEST(_GraphGenerator, CalculateAndStoreStepType) { EmbreeRayTracer ray_tracer = CreateGGExmapleRT(); - //! [EX_CheckStepTypes] // Create graph parameters HF::GraphGenerator::GraphParams params; @@ -713,6 +713,7 @@ TEST(_GraphGenerator, CalculateAndStoreStepType) { params.precision.node_z = 0.01f; params.precision.ground_offset = 0.01f; + // Construct graph Graph g; Node N0 = Node(0, 0, 1); Node N1 = Node(0, 2, 0); @@ -727,20 +728,64 @@ TEST(_GraphGenerator, CalculateAndStoreStepType) { g.Compress(); + // Compute and store step types in graph CalculateAndStoreStepType(g, HF::RayTracer::MultiRT(&ray_tracer), params); std::vector result = g.GetEdges("step_type"); - HF::SpatialStructures::EdgeSet node_one_edgeset = result[0]; - std::vector node_one_inteedges = node_one_edgeset.children; + // Testing node 0's edges + HF::SpatialStructures::EdgeSet node_zero_edgeset = result[0]; + std::vector node_zero_inteedges = node_zero_edgeset.children; std::vector expected_step_types = { 1,0,0,1 }; for (int i = 0; i < expected_step_types.size(); i++) { - float step_type = node_one_inteedges[i].weight; + float step_type = node_zero_inteedges[i].weight; ASSERT_EQ(step_type, expected_step_types[i]); } +} + +TEST(_GraphGenerator, CalculateAndStoreStepTypes) { + EmbreeRayTracer ray_tracer = CreateGGExmapleRT(); + // Create graph parameters + HF::GraphGenerator::GraphParams params; + params.up_step = 2; params.down_step = 2; + params.up_slope = 45; params.down_slope = 45; + params.precision.node_z = 0.01f; + params.precision.ground_offset = 0.01f; + + // Construct graph + Graph g; + Node N0 = Node(0, 0, 1); + Node N1 = Node(0, 2, 0); + Node N2 = Node(1, 0, 0); + Node N3 = Node(0, 1, 0); + Node N4 = Node(2, 0, 0); + + g.addEdge(N0, N1); + g.addEdge(N0, N2); + g.addEdge(N0, N3); + g.addEdge(N0, N4); + + g.Compress(); + + // Compute and store step types in graph + + CalculateAndStoreStepTypes(&g, &ray_tracer, params.up_step, params.down_step, params.up_slope, params.down_slope, params.precision.ground_offset, params.precision.node_z, params.precision.node_spacing); + + std::vector result = g.GetEdges("step_type"); + + // Testing node 0's edges + HF::SpatialStructures::EdgeSet node_zero_edgeset = result[0]; + std::vector node_zero_inteedges = node_zero_edgeset.children; + + std::vector expected_step_types = { 1,0,0,1 }; + + for (int i = 0; i < expected_step_types.size(); i++) { + float step_type = node_zero_inteedges[i].weight; + ASSERT_EQ(step_type, expected_step_types[i]); + } } diff --git a/src/Python/dhart/graphgenerator/graph_generator.py b/src/Python/dhart/graphgenerator/graph_generator.py index 34779185c..87b17194a 100644 --- a/src/Python/dhart/graphgenerator/graph_generator.py +++ b/src/Python/dhart/graphgenerator/graph_generator.py @@ -143,3 +143,27 @@ def GenerateGraph( return Graph(pointer) else: return None + +def CalculateAndStoreStepTypes( + g: Graph, + bvh: EmbreeBVH, + up_step: float = 0.197, + up_slope: float = 20, + down_step: float = 0.197, + down_slope: float = 20, + ground_offset: float = 0.01, + node_z: float = 0.0001, + node_spacing: float = 0.00001 +) -> None: + + graph_generator_native_functions.CalculateAndStoreStepTypes( + g.graph_ptr, + bvh.pointer, + up_step, + up_slope, + down_step, + down_slope, + ground_offset, + node_z, + node_spacing + ) diff --git a/src/Python/dhart/graphgenerator/graph_generator_native_functions.py b/src/Python/dhart/graphgenerator/graph_generator_native_functions.py index bd1d529ac..3d950d833 100644 --- a/src/Python/dhart/graphgenerator/graph_generator_native_functions.py +++ b/src/Python/dhart/graphgenerator/graph_generator_native_functions.py @@ -98,4 +98,32 @@ def GenerateGraph( return graph_ptr elif error_code == HF_STATUS.NO_GRAPH: return None - \ No newline at end of file + +def CalculateAndStoreStepTypes( + graph_ptr : c_void_p, + rt_ptr: c_void_p, + up_step: float, + up_slope: float, + down_step: float, + down_slope: float, + ground_offset: float, + node_z: float, + node_spacing: float +) -> None: + """Queries the graph's step types and adds them as edges to the graph. + + Returns: + None + """ + error_code = HFPython.CalculateAndStoreStepTypes( + graph_ptr, + rt_ptr, + c_float(up_step), + c_float(down_step), + c_float(up_slope), + c_float(down_slope), + c_float(ground_offset), + c_float(node_z), + c_float(node_spacing) + ) + assert(error_code == HF_STATUS.OK) \ No newline at end of file diff --git a/src/Python/dhart/graphgenerator/test_GraphGenerator.py b/src/Python/dhart/graphgenerator/test_GraphGenerator.py index 1a42ada69..089534dd3 100644 --- a/src/Python/dhart/graphgenerator/test_GraphGenerator.py +++ b/src/Python/dhart/graphgenerator/test_GraphGenerator.py @@ -2,7 +2,8 @@ from dhart.geometry import LoadOBJ, CommonRotations, OBJGroupType from dhart.raytracer import EmbreeBVH -from dhart.graphgenerator.graph_generator import GenerateGraph +from dhart.graphgenerator.graph_generator import GenerateGraph, CalculateAndStoreStepTypes +from dhart.spatialstructures.graph import * import dhart def test_GetNodes(): @@ -109,4 +110,32 @@ def test_obstacle_support(): ) assert(obstacle_graph is not None) - assert(obstacle_graph.NumNodes() < non_obstacle_graph.NumNodes()) \ No newline at end of file + assert(obstacle_graph.NumNodes() < non_obstacle_graph.NumNodes()) + +def test_step_type_query(): + mesh_path = dhart.get_sample_model("plane.obj") + obj = LoadOBJ(mesh_path, rotation=CommonRotations.Yup_to_Zup) + bvh = EmbreeBVH(obj) + + g = Graph() + + g.AddEdgeToGraph((0,0,1), (0,2,0), -1) + g.AddEdgeToGraph((0,0,1), (1,0,0), -1) + g.AddEdgeToGraph((0,0,1), (0,1,0), -1) + g.AddEdgeToGraph((0,0,1), (2,0,0), -1) + + up_step, up_slope = 2, 45 + down_step, down_slope = 2, 45 + node_z = 0.01 + ground_offset = 0.01 + + CalculateAndStoreStepTypes( + g, bvh, up_step, up_slope, down_step, down_slope, node_z, ground_offset + ) + + expected_steps = [1, 0, 0, 1] + parent = 0 + for child in range(1, 5): + result_step = g.GetEdgeCost(parent, child, "step_type") + assert(result_step == expected_steps[i-1]) + From 02a7f7ab57d54961946c132cef29e621315578df Mon Sep 17 00:00:00 2001 From: Christopher Liem Date: Thu, 23 Jan 2025 15:03:34 -0500 Subject: [PATCH 04/10] Step Type Query (Python) --- src/Cinterface/analysis_C.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Cinterface/analysis_C.cpp b/src/Cinterface/analysis_C.cpp index 28f1fe167..f06cfbb1d 100644 --- a/src/Cinterface/analysis_C.cpp +++ b/src/Cinterface/analysis_C.cpp @@ -126,6 +126,8 @@ C_INTERFACE CalculateAndStoreStepTypes( params.precision.ground_offset = ground_offset; params.precision.node_z = node_z; params.precision.node_spacing = node_spacing; + + g->Compress(); auto result = CalculateStepType(*g, HF::RayTracer::MultiRT(ray_tracer), params); From d49014d3b894c40e56bb6e8392ba38ebdd74646d Mon Sep 17 00:00:00 2001 From: Christopher Liem Date: Thu, 23 Jan 2025 15:08:22 -0500 Subject: [PATCH 05/10] Compress Graph before query --- src/Cpp/analysismethods/src/graph_utils.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Cpp/analysismethods/src/graph_utils.cpp b/src/Cpp/analysismethods/src/graph_utils.cpp index 631ed6160..fb784c9b4 100644 --- a/src/Cpp/analysismethods/src/graph_utils.cpp +++ b/src/Cpp/analysismethods/src/graph_utils.cpp @@ -371,6 +371,7 @@ namespace HF::GraphGenerator { void CalculateAndStoreStepType(HF::SpatialStructures::Graph& g, HF::RayTracer::MultiRT& rt, const GraphParams& params) { // calculates and stores step types of all edges and stores it in the graph + g.Compress() // Get all edges with weights corresponding to step type auto result = HF::GraphGenerator::CalculateStepType(g, rt, params); From 31a7713114a360bb280e0032c4fc9c014acce683 Mon Sep 17 00:00:00 2001 From: Christopher Liem Date: Thu, 23 Jan 2025 15:12:44 -0500 Subject: [PATCH 06/10] Compression needed before adding step types --- src/Cpp/analysismethods/src/graph_utils.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Cpp/analysismethods/src/graph_utils.cpp b/src/Cpp/analysismethods/src/graph_utils.cpp index fb784c9b4..03db468f8 100644 --- a/src/Cpp/analysismethods/src/graph_utils.cpp +++ b/src/Cpp/analysismethods/src/graph_utils.cpp @@ -371,11 +371,13 @@ namespace HF::GraphGenerator { void CalculateAndStoreStepType(HF::SpatialStructures::Graph& g, HF::RayTracer::MultiRT& rt, const GraphParams& params) { // calculates and stores step types of all edges and stores it in the graph - g.Compress() // Get all edges with weights corresponding to step type auto result = HF::GraphGenerator::CalculateStepType(g, rt, params); + // Compression needed before adding edges of alternate cost + g.Compress(); + // Add edges to the graph g.AddEdges(result, "step_type"); } From 5c4b2c3ba61859a0cc9166f639ff52b526e35965 Mon Sep 17 00:00:00 2001 From: coliem Date: Sat, 25 Jan 2025 01:37:26 -0500 Subject: [PATCH 07/10] Removed parameters from step functions & modified UnitTests --- src/CMakeLists.txt | 2 +- src/Cinterface/analysis_C.cpp | 20 +- src/Cinterface/analysis_C.h | 29 +-- src/Cpp/analysismethods/src/graph_generator.h | 34 ++- src/Cpp/analysismethods/src/graph_utils.cpp | 97 ++++++++- src/Cpp/tests/src/GraphGenerator.cpp | 193 ++++++++++-------- 6 files changed, 230 insertions(+), 145 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dfe9b9acb..dc72aaee2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,7 +19,7 @@ set(DEBUG_DEPENDENCY_BINARIES "${CMAKE_SOURCE_DIR}/external/Microsoft/cpp/Debug/vcomp140d.dll" "${CMAKE_SOURCE_DIR}/external/Microsoft/cpp/Debug/msvcp140d.dll" ) - + set(RELEASE_DEPENDENCY_BINARIES "${CMAKE_SOURCE_DIR}/external/Microsoft/cpp/Release/vcruntime140_1.dll" "${CMAKE_SOURCE_DIR}/external/Microsoft/cpp/Release/vcomp140.dll" diff --git a/src/Cinterface/analysis_C.cpp b/src/Cinterface/analysis_C.cpp index f06cfbb1d..e88969575 100644 --- a/src/Cinterface/analysis_C.cpp +++ b/src/Cinterface/analysis_C.cpp @@ -108,28 +108,12 @@ C_INTERFACE GenerateGraphObstacles( C_INTERFACE CalculateAndStoreStepTypes( HF::SpatialStructures::Graph* g, - HF::RayTracer::EmbreeRayTracer* ray_tracer, - float up_step, - float down_step, - float up_slope, - float down_slope, - float ground_offset, - float node_z, - float node_spacing + HF::RayTracer::EmbreeRayTracer* ray_tracer ) { - HF::GraphGenerator::Precision precision = { node_z, node_spacing, ground_offset }; - HF::GraphGenerator::GraphParams params; - - //Setup params struct - params.up_step = up_step; params.down_step = down_step; - params.up_slope = up_slope; params.down_slope = down_slope; - params.precision.ground_offset = ground_offset; - params.precision.node_z = node_z; - params.precision.node_spacing = node_spacing; g->Compress(); - auto result = CalculateStepType(*g, HF::RayTracer::MultiRT(ray_tracer), params); + auto result = HF::GraphGenerator::CalculateStepType(*g, HF::RayTracer::MultiRT(ray_tracer)); g->AddEdges(result, "step_type"); diff --git a/src/Cinterface/analysis_C.h b/src/Cinterface/analysis_C.h index 75cb177df..d674b2c0c 100644 --- a/src/Cinterface/analysis_C.h +++ b/src/Cinterface/analysis_C.h @@ -230,38 +230,13 @@ C_INTERFACE GenerateGraphObstacles( \param ray_tracer Raytracer containing the geometry to use for graph generation. - \param up_step Maximum height of a step the graph can traverse. - Any steps higher this will be considered inaccessible. - - \param up_slope Maximum upward slope the graph can traverse in degrees. - Any slopes steeper than this will be considered inaccessible. - - \param down_step Maximum step down the graph can traverse. - Any steps steeper than this will be considered inaccessible. - - \param down_slope The maximum downward slope the graph can traverse. - Any slopes steeper than this will be considered inaccessible. - - \param ground_offset Distance to offset nodes from the ground before checking line of sight. - - \param node_z Precision to round the z-component of nodes after a raycast is performed. - - \param node_spacing Precision to round nodes after spacing is calculated. - \returns \link HF_STATUS::OK \endlink if query was successful and edges corresponding to step types have been added to the graph. */ C_INTERFACE CalculateAndStoreStepTypes( HF::SpatialStructures::Graph* g, - HF::RayTracer::EmbreeRayTracer* ray_tracer, - float up_step, - float down_step, - float up_slope, - float down_slope, - float ground_offset, - float node_z, - float node_spacing + HF::RayTracer::EmbreeRayTracer* ray_tracer ); -/**@}*/ +/**@}*/ #endif /* ANALYSIS_C_H */ diff --git a/src/Cpp/analysismethods/src/graph_generator.h b/src/Cpp/analysismethods/src/graph_generator.h index d13d6bb62..a7fb768ed 100644 --- a/src/Cpp/analysismethods/src/graph_generator.h +++ b/src/Cpp/analysismethods/src/graph_generator.h @@ -761,7 +761,26 @@ namespace HF::GraphGenerator { RayTracer& rt, const GraphParams & params ); + /*! + \brief Determine what kind of step (if any) is between parent and child, given + that a connection was verified using the graph generator. + + \param parent Node being traversed from + \param child Node being traversed to + \param rt Raytracer to use for all ray intersections + \returns The type of step between parent/child. + + \par Example + \snippet tests\src\GraphGenerator.cpp EX_GraphGeneratorRayTracer + \snippet tests\src\GraphGenerator.cpp EX_CheckConnection + `[1,0,0,1]` + */ + HF::SpatialStructures::STEP CheckConnection( + const real3& parent, + const real3& child, + RayTracer& rt + ); /*! \brief Determine what kind of step (if any) is between parent and child. @@ -787,22 +806,25 @@ namespace HF::GraphGenerator { HF::SpatialStructures::EdgeSet CalculateStepType( const HF::SpatialStructures::Subgraph& sg, - HF::RayTracer::MultiRT& rt, - const GraphParams& params + HF::RayTracer::MultiRT& rt ); std::vector CalculateStepType( const HF::SpatialStructures::Graph& g, - HF::RayTracer::MultiRT& rt, - const GraphParams& params + HF::RayTracer::MultiRT& rt ); void CalculateAndStoreStepType( HF::SpatialStructures::Graph& g, - HF::RayTracer::MultiRT& rt, - const GraphParams& params + HF::RayTracer::MultiRT& rt ); + bool CompareCheckConnections( + HF::SpatialStructures::Graph& g, + RayTracer& rt, + const GraphParams& params, + std::vector < HF::SpatialStructures::EdgeSet> to_compare + ); /*! \brief Determine if there is a valid line of sight between parent and child diff --git a/src/Cpp/analysismethods/src/graph_utils.cpp b/src/Cpp/analysismethods/src/graph_utils.cpp index 03db468f8..c65937a71 100644 --- a/src/Cpp/analysismethods/src/graph_utils.cpp +++ b/src/Cpp/analysismethods/src/graph_utils.cpp @@ -300,7 +300,7 @@ namespace HF::GraphGenerator { return calc_slope > -1.0 * gp.down_slope && calc_slope < gp.up_slope; } - HF::SpatialStructures::EdgeSet CalculateStepType(const HF::SpatialStructures::Subgraph& sg, HF::RayTracer::MultiRT& rt, const GraphParams& params) { + HF::SpatialStructures::EdgeSet CalculateStepType(const HF::SpatialStructures::Subgraph& sg, HF::RayTracer::MultiRT& rt) { // Step type will be stored here and returned from this function //Initialize output @@ -335,7 +335,7 @@ namespace HF::GraphGenerator { real3 child_cast = CastToReal3(child_loc); //Get the step type between parent and child - STEP step_type = CheckConnection(parent_cast, child_cast, rt, params); + STEP step_type = CheckConnection(parent_cast, child_cast, rt); //Construct an intedge for this parent-child pair to add to edgeset HF::SpatialStructures::IntEdge ie = { link_a.child.id, static_cast(step_type) }; @@ -348,7 +348,7 @@ namespace HF::GraphGenerator { return es; } - std::vector CalculateStepType(const HF::SpatialStructures::Graph& g, HF::RayTracer::MultiRT& rt, const GraphParams& params) { + std::vector CalculateStepType(const HF::SpatialStructures::Graph& g, HF::RayTracer::MultiRT& rt) { // Retrieve all nodes from g so we can obtain subgraphs. std::vector nodes = g.Nodes(); @@ -362,26 +362,71 @@ namespace HF::GraphGenerator { HF::SpatialStructures::Subgraph sg = g.GetSubgraph(parent_node); // Call CalculateStepType using the subgraph - HF::SpatialStructures::EdgeSet step_types = CalculateStepType(sg, rt, params); + HF::SpatialStructures::EdgeSet step_types = CalculateStepType(sg, rt); *(it_result++) = step_types; } return result; } - void CalculateAndStoreStepType(HF::SpatialStructures::Graph& g, HF::RayTracer::MultiRT& rt, const GraphParams& params) { + void CalculateAndStoreStepType(HF::SpatialStructures::Graph& g, HF::RayTracer::MultiRT& rt) { // calculates and stores step types of all edges and stores it in the graph - // Get all edges with weights corresponding to step type - auto result = HF::GraphGenerator::CalculateStepType(g, rt, params); - // Compression needed before adding edges of alternate cost g.Compress(); + // Get all edges with weights corresponding to step type + auto result = HF::GraphGenerator::CalculateStepType(g, rt); + // Add edges to the graph g.AddEdges(result, "step_type"); } + HF::SpatialStructures::STEP CheckConnection( + const real3& parent, + const real3& child, + RayTracer& rt) + { + // Default graphh generator ground offset + const auto GROUND_OFFSET = 0.01; + + // Create a copy of parent and child that can be modified + auto node1 = parent; + auto node2 = child; + + // Offset them from the ground slightly + node1[2] += GROUND_OFFSET; + node2[2] += GROUND_OFFSET; + + if (!OcclusionCheck(node1, node2, rt)) { + // Case for when there is direct line of sight between nodes. + // Since the edge is already in the graph, we do not need to check whether + // they're on the same plane or if the slope between them is valid. + return STEP::NONE; + } + // Otherwise check for step based connections. + else { + // Since these edges were already verified in the graph generator, + // we do not need to check line of sight changes using offsets. + STEP s = STEP::NONE; + + // If parent is higher than child, then we have a down step + if (parent[2] > child[2]) { + s = STEP::DOWN; + } + // If parent is lower than child, then we have an up step. + else if (parent[2] < child[2]) { + s = STEP::UP; + } + // If parent is on an equal plane with the child, then we step over an obstacle. + else if (parent[2] == child[2]) { + s = STEP::OVER; + } + return s; + } + + } + HF::SpatialStructures::STEP CheckConnection( const real3& parent, const real3& child, @@ -460,6 +505,42 @@ namespace HF::GraphGenerator { return STEP::NOT_CONNECTED; } + bool CompareCheckConnections(HF::SpatialStructures::Graph& g, RayTracer& rt, + const GraphParams& params, std::vector < HF::SpatialStructures::EdgeSet> to_compare) + { + const auto graph_nodes = g.Nodes(); + for (Node node : graph_nodes) { + int parent_id = node.id; + std::vector outgoing_edges = to_compare[parent_id].children; + for (HF::SpatialStructures::IntEdge edge : outgoing_edges) { + int child_id = edge.child; + float step_type = edge.weight; + Node child = g.NodeFromID(child_id); + + //Type Casting + real_t parent_x = CastToReal(node.x); + real_t parent_y = CastToReal(node.y); + real_t parent_z = CastToReal(node.z); + + real_t child_x = CastToReal(child.x); + real_t child_y = CastToReal(child.y); + real_t child_z = CastToReal(child.z); + + std::vector parent_loc = { parent_x, parent_y, parent_z }; + std::vector child_loc = { child_x, child_y, child_z }; + + real3 parent_cast = CastToReal3(parent_loc); + real3 child_cast = CastToReal3(child_loc); + + float expected_step_type = static_cast(CheckConnection(parent_cast, child_cast, + rt, params)); + if (expected_step_type != 0 && expected_step_type != step_type) { + return false; + } + } + } + return true; + } std::vector GeneratePotentialChildren( const real3& parent, const std::vector& directions, diff --git a/src/Cpp/tests/src/GraphGenerator.cpp b/src/Cpp/tests/src/GraphGenerator.cpp index 06a753b1e..58e6e44fc 100644 --- a/src/Cpp/tests/src/GraphGenerator.cpp +++ b/src/Cpp/tests/src/GraphGenerator.cpp @@ -167,7 +167,7 @@ TEST(_GraphGenerator, OutDegree) { //! [EX_OutDegree] - auto out_str = PrintGraph(g); + //auto out_str = PrintGraph(g); const auto graph_nodes = g.Nodes(); @@ -665,127 +665,150 @@ TEST(_GraphGenerator, OcclusionCheck) { } TEST(_GraphGenerator, CalculateStepType) { - EmbreeRayTracer ray_tracer = CreateGGExmapleRT(); + // Load an OBJ containing a simple plane + auto mesh = HF::Geometry::LoadMeshObjects("energy_blob_zup.obj", HF::Geometry::ONLY_FILE, false); + + // Create a raytracer using this obj + EmbreeRayTracer ray_tracer = HF::RayTracer::EmbreeRayTracer(mesh); //! [EX_CheckStepTypes] - // Create graph parameters + // Create a graphgenerator using the raytracer we just created + HF::GraphGenerator::GraphGenerator GG = GraphGenerator::GraphGenerator(ray_tracer); + + // Setup Graph Parameters + std::array start_point{ 0,0,20 }; + std::array spacing{ 1,1,1 }; + HF::GraphGenerator::GraphParams params; - params.up_step = 2; params.down_step = 2; - params.up_slope = 45; params.down_slope = 45; - params.precision.node_z = 0.01f; - params.precision.ground_offset = 0.01f; - Graph g; - Node N0 = Node(0, 0, 1); - Node N1 = Node(0, 2, 0); - Node N2 = Node(1, 0, 0); - Node N3 = Node(0, 1, 0); - Node N4 = Node(2, 0, 0); + int max_nodes = 5000; + params.up_step = 0.5; params.down_step = 0.5; + params.up_slope = 20; params.down_slope = 20; + int max_step_connections = 1; + int min_connections = 4; + params.precision.node_z = 0.0001; + params.precision.ground_offset = 0.01; + params.precision.node_spacing = 0.00001; - g.addEdge(N0, N1); - g.addEdge(N0, N2); - g.addEdge(N0, N3); - g.addEdge(N0, N4); + // Generate the graph using our parameters + HF::SpatialStructures::Graph g = GG.BuildNetwork( + start_point, + spacing, + max_nodes, + params.up_step, params.up_slope, + params.down_step, params.down_slope, + max_step_connections, + min_connections + ); + // Compression needed to access step types g.Compress(); - std::vector step_types = HF::GraphGenerator::CalculateStepType(g, HF::RayTracer::MultiRT(&ray_tracer), params); + // Compute all step types and store in std::vector + auto step_types = HF::GraphGenerator::CalculateStepType(g, HF::RayTracer::MultiRT(&ray_tracer)); - HF::SpatialStructures::EdgeSet node_one_edgeset = step_types[0]; - std::vector node_one_inteedges = node_one_edgeset.children; + // Compare result to CheckConnection results for initial graph generation. + bool equal_connections = HF::GraphGenerator::CompareCheckConnections(g, HF::RayTracer::MultiRT(&ray_tracer), + params, step_types); - std::vector expected_step_types = { 1,0,0,1 }; - - for (int i = 0; i < expected_step_types.size(); i++) { - float step_type = node_one_inteedges[i].weight; - ASSERT_EQ(step_type, expected_step_types[i]); - } + ASSERT_TRUE(equal_connections); //! [EX_CheckStepTypes] } TEST(_GraphGenerator, CalculateAndStoreStepType) { - EmbreeRayTracer ray_tracer = CreateGGExmapleRT(); + // Load an OBJ containing a simple plane + auto mesh = HF::Geometry::LoadMeshObjects("energy_blob_zup.obj", HF::Geometry::ONLY_FILE, false); - // Create graph parameters - HF::GraphGenerator::GraphParams params; - params.up_step = 2; params.down_step = 2; - params.up_slope = 45; params.down_slope = 45; - params.precision.node_z = 0.01f; - params.precision.ground_offset = 0.01f; + // Create a raytracer using this obj + EmbreeRayTracer ray_tracer = HF::RayTracer::EmbreeRayTracer(mesh); + //! [EX_CheckStepTypes] - // Construct graph - Graph g; - Node N0 = Node(0, 0, 1); - Node N1 = Node(0, 2, 0); - Node N2 = Node(1, 0, 0); - Node N3 = Node(0, 1, 0); - Node N4 = Node(2, 0, 0); + // Create a graphgenerator using the raytracer we just created + HF::GraphGenerator::GraphGenerator GG = GraphGenerator::GraphGenerator(ray_tracer); - g.addEdge(N0, N1); - g.addEdge(N0, N2); - g.addEdge(N0, N3); - g.addEdge(N0, N4); + // Setup Graph Parameters + std::array start_point{ 0,0,20 }; + std::array spacing{ 1,1,1 }; - g.Compress(); + HF::GraphGenerator::GraphParams params; + + int max_nodes = 5000; + params.up_step = 0.5; params.down_step = 0.5; + params.up_slope = 20; params.down_slope = 20; + int max_step_connections = 1; + int min_connections = 4; + params.precision.node_z = 0.0001; + params.precision.ground_offset = 0.01; + params.precision.node_spacing = 0.00001; + + // Generate the graph using our parameters + HF::SpatialStructures::Graph g = GG.BuildNetwork( + start_point, + spacing, + max_nodes, + params.up_step, params.up_slope, + params.down_step, params.down_slope, + max_step_connections, + min_connections + ); // Compute and store step types in graph - CalculateAndStoreStepType(g, HF::RayTracer::MultiRT(&ray_tracer), params); + HF::GraphGenerator::CalculateAndStoreStepType(g, HF::RayTracer::MultiRT(&ray_tracer)); std::vector result = g.GetEdges("step_type"); - // Testing node 0's edges - HF::SpatialStructures::EdgeSet node_zero_edgeset = result[0]; - std::vector node_zero_inteedges = node_zero_edgeset.children; + bool equal_connections = HF::GraphGenerator::CompareCheckConnections(g, HF::RayTracer::MultiRT(&ray_tracer), + params, result); - std::vector expected_step_types = { 1,0,0,1 }; - - for (int i = 0; i < expected_step_types.size(); i++) { - float step_type = node_zero_inteedges[i].weight; - ASSERT_EQ(step_type, expected_step_types[i]); - } + ASSERT_TRUE(equal_connections); } TEST(_GraphGenerator, CalculateAndStoreStepTypes) { - EmbreeRayTracer ray_tracer = CreateGGExmapleRT(); + // Load an OBJ containing a simple plane + auto mesh = HF::Geometry::LoadMeshObjects("energy_blob_zup.obj", HF::Geometry::ONLY_FILE, false); - // Create graph parameters - HF::GraphGenerator::GraphParams params; - params.up_step = 2; params.down_step = 2; - params.up_slope = 45; params.down_slope = 45; - params.precision.node_z = 0.01f; - params.precision.ground_offset = 0.01f; + // Create a raytracer using this obj + EmbreeRayTracer ray_tracer = HF::RayTracer::EmbreeRayTracer(mesh); + //! [EX_CheckStepTypes] - // Construct graph - Graph g; - Node N0 = Node(0, 0, 1); - Node N1 = Node(0, 2, 0); - Node N2 = Node(1, 0, 0); - Node N3 = Node(0, 1, 0); - Node N4 = Node(2, 0, 0); + // Create a graphgenerator using the raytracer we just created + HF::GraphGenerator::GraphGenerator GG = GraphGenerator::GraphGenerator(ray_tracer); - g.addEdge(N0, N1); - g.addEdge(N0, N2); - g.addEdge(N0, N3); - g.addEdge(N0, N4); + // Setup Graph Parameters + std::array start_point{ 0,0,20 }; + std::array spacing{ 1,1,1 }; - g.Compress(); + HF::GraphGenerator::GraphParams params; - // Compute and store step types in graph + int max_nodes = 5000; + params.up_step = 0.5; params.down_step = 0.5; + params.up_slope = 20; params.down_slope = 20; + int max_step_connections = 1; + int min_connections = 4; + params.precision.node_z = 0.0001; + params.precision.ground_offset = 0.01; + params.precision.node_spacing = 0.00001; - CalculateAndStoreStepTypes(&g, &ray_tracer, params.up_step, params.down_step, params.up_slope, params.down_slope, params.precision.ground_offset, params.precision.node_z, params.precision.node_spacing); + // Generate the graph using our parameters + HF::SpatialStructures::Graph g = GG.BuildNetwork( + start_point, + spacing, + max_nodes, + params.up_step, params.up_slope, + params.down_step, params.down_slope, + max_step_connections, + min_connections + ); - std::vector result = g.GetEdges("step_type"); + // Compute and store step types in graph + CalculateAndStoreStepTypes(&g, &ray_tracer); - // Testing node 0's edges - HF::SpatialStructures::EdgeSet node_zero_edgeset = result[0]; - std::vector node_zero_inteedges = node_zero_edgeset.children; + std::vector result = g.GetEdges("step_type"); - std::vector expected_step_types = { 1,0,0,1 }; + bool equal_connections = HF::GraphGenerator::CompareCheckConnections(g, HF::RayTracer::MultiRT(&ray_tracer), + params, result); - for (int i = 0; i < expected_step_types.size(); i++) { - float step_type = node_zero_inteedges[i].weight; - ASSERT_EQ(step_type, expected_step_types[i]); - } + ASSERT_TRUE(equal_connections); } From edc89b17eeb1f566738ea4540910bc95e9a5a725 Mon Sep 17 00:00:00 2001 From: coliem Date: Sat, 25 Jan 2025 01:59:44 -0500 Subject: [PATCH 08/10] Removed extra parameters from step Python functions --- .../dhart/graphgenerator/graph_generator.py | 18 ++---------------- .../graph_generator_native_functions.py | 14 -------------- .../graphgenerator/test_GraphGenerator.py | 13 +++++-------- 3 files changed, 7 insertions(+), 38 deletions(-) diff --git a/src/Python/dhart/graphgenerator/graph_generator.py b/src/Python/dhart/graphgenerator/graph_generator.py index 87b17194a..852f8a62f 100644 --- a/src/Python/dhart/graphgenerator/graph_generator.py +++ b/src/Python/dhart/graphgenerator/graph_generator.py @@ -146,24 +146,10 @@ def GenerateGraph( def CalculateAndStoreStepTypes( g: Graph, - bvh: EmbreeBVH, - up_step: float = 0.197, - up_slope: float = 20, - down_step: float = 0.197, - down_slope: float = 20, - ground_offset: float = 0.01, - node_z: float = 0.0001, - node_spacing: float = 0.00001 + bvh: EmbreeBVH ) -> None: graph_generator_native_functions.CalculateAndStoreStepTypes( g.graph_ptr, - bvh.pointer, - up_step, - up_slope, - down_step, - down_slope, - ground_offset, - node_z, - node_spacing + bvh.pointer ) diff --git a/src/Python/dhart/graphgenerator/graph_generator_native_functions.py b/src/Python/dhart/graphgenerator/graph_generator_native_functions.py index 3d950d833..40907180d 100644 --- a/src/Python/dhart/graphgenerator/graph_generator_native_functions.py +++ b/src/Python/dhart/graphgenerator/graph_generator_native_functions.py @@ -102,13 +102,6 @@ def GenerateGraph( def CalculateAndStoreStepTypes( graph_ptr : c_void_p, rt_ptr: c_void_p, - up_step: float, - up_slope: float, - down_step: float, - down_slope: float, - ground_offset: float, - node_z: float, - node_spacing: float ) -> None: """Queries the graph's step types and adds them as edges to the graph. @@ -118,12 +111,5 @@ def CalculateAndStoreStepTypes( error_code = HFPython.CalculateAndStoreStepTypes( graph_ptr, rt_ptr, - c_float(up_step), - c_float(down_step), - c_float(up_slope), - c_float(down_slope), - c_float(ground_offset), - c_float(node_z), - c_float(node_spacing) ) assert(error_code == HF_STATUS.OK) \ No newline at end of file diff --git a/src/Python/dhart/graphgenerator/test_GraphGenerator.py b/src/Python/dhart/graphgenerator/test_GraphGenerator.py index 089534dd3..0bc63c05a 100644 --- a/src/Python/dhart/graphgenerator/test_GraphGenerator.py +++ b/src/Python/dhart/graphgenerator/test_GraphGenerator.py @@ -120,8 +120,6 @@ def test_step_type_query(): g = Graph() g.AddEdgeToGraph((0,0,1), (0,2,0), -1) - g.AddEdgeToGraph((0,0,1), (1,0,0), -1) - g.AddEdgeToGraph((0,0,1), (0,1,0), -1) g.AddEdgeToGraph((0,0,1), (2,0,0), -1) up_step, up_slope = 2, 45 @@ -129,13 +127,12 @@ def test_step_type_query(): node_z = 0.01 ground_offset = 0.01 - CalculateAndStoreStepTypes( - g, bvh, up_step, up_slope, down_step, down_slope, node_z, ground_offset - ) + CalculateAndStoreStepTypes(g, bvh) - expected_steps = [1, 0, 0, 1] + expected_steps = [1,1] parent = 0 - for child in range(1, 5): + for child in range(1, 3): + print(g.GetEdgeCost(parent, child, "step_type")) result_step = g.GetEdgeCost(parent, child, "step_type") - assert(result_step == expected_steps[i-1]) + assert(result_step == expected_steps[child-1]) From fb5ea06e31593ccf70f47b42f62b56979ed82530 Mon Sep 17 00:00:00 2001 From: coliem Date: Mon, 27 Jan 2025 12:54:28 -0500 Subject: [PATCH 09/10] Improved Python UnitTtests for step types + Docstring for CalculateAndStoreStepTypes --- .../dhart/graphgenerator/graph_generator.py | 39 +++++++++++++ .../graphgenerator/test_GraphGenerator.py | 55 +++++++++++++------ 2 files changed, 78 insertions(+), 16 deletions(-) diff --git a/src/Python/dhart/graphgenerator/graph_generator.py b/src/Python/dhart/graphgenerator/graph_generator.py index 852f8a62f..2562f2b51 100644 --- a/src/Python/dhart/graphgenerator/graph_generator.py +++ b/src/Python/dhart/graphgenerator/graph_generator.py @@ -148,7 +148,46 @@ def CalculateAndStoreStepTypes( g: Graph, bvh: EmbreeBVH ) -> None: + """Calculates and stores the step types of all edges in a given graph. It will be stored as cost type "step_type." + Args: + g (Graph): Graph to query step types on. + bvh (EmbreeBVH): Geometry to use for graph generation. The mesh used + to generate the BVH must have been Z-up. + + Returns: + None + + Examples: + Generate a graph and query its step types. + >>> from dhart.geometry import LoadOBJ, MeshInfo, CommonRotations + >>> from dhart.raytracer import EmbreeBVH + >>> from dhart.geometry.mesh_info import ConstructPlane + >>> from dhart.graphgenerator import GenerateGraph + >>> import dhart + + >>> obj_path = dhart.get_sample_model("energy_blob_zup.obj") + >>> obj = LoadOBJ(obj_path) + >>> bvh = EmbreeBVH(obj, True) + + >>> start_point = (0, 0, 20) + >>> spacing = (1, 1, 1) + >>> max_nodes = 5000 + >>> up_step, down_step = 0.5, 0.5 + >>> up_slope, down_slope = 20, 20 + >>> max_step_connections = 1 + >>> min_connections = 4 + + >>> g = GenerateGraph(bvh, start_point, spacing, max_nodes, + up_step,up_slope,down_step,down_slope, + max_step_connections, min_connections) + + + >>> CalculateAndStoreStepTypes(g, bvh) + + >>> print(g.GetEdgeCost(0, 1, "step_type")) + 3.0 + """ graph_generator_native_functions.CalculateAndStoreStepTypes( g.graph_ptr, bvh.pointer diff --git a/src/Python/dhart/graphgenerator/test_GraphGenerator.py b/src/Python/dhart/graphgenerator/test_GraphGenerator.py index 0bc63c05a..f194d5d56 100644 --- a/src/Python/dhart/graphgenerator/test_GraphGenerator.py +++ b/src/Python/dhart/graphgenerator/test_GraphGenerator.py @@ -113,26 +113,49 @@ def test_obstacle_support(): assert(obstacle_graph.NumNodes() < non_obstacle_graph.NumNodes()) def test_step_type_query(): - mesh_path = dhart.get_sample_model("plane.obj") - obj = LoadOBJ(mesh_path, rotation=CommonRotations.Yup_to_Zup) - bvh = EmbreeBVH(obj) + # Get a sample model path + obj_path = dhart.get_sample_model("energy_blob_zup.obj") - g = Graph() + # Load the obj file + obj = LoadOBJ(obj_path) - g.AddEdgeToGraph((0,0,1), (0,2,0), -1) - g.AddEdgeToGraph((0,0,1), (2,0,0), -1) + # Create a BVH + bvh = EmbreeBVH(obj, True) + + # Set the graph parameters + start_point = (0, 0, 20) + spacing = (1, 1, 1) + max_nodes = 5000 + up_step, down_step = 0.5, 0.5 + up_slope, down_slope = 20, 20 + max_step_connections = 1 + min_connections = 4 + cores = -1 + + g = GenerateGraph(bvh, start_point, spacing, max_nodes, + up_step,up_slope,down_step,down_slope, + max_step_connections, min_connections, + cores) - up_step, up_slope = 2, 45 - down_step, down_slope = 2, 45 - node_z = 0.01 - ground_offset = 0.01 CalculateAndStoreStepTypes(g, bvh) - expected_steps = [1,1] - parent = 0 - for child in range(1, 3): - print(g.GetEdgeCost(parent, child, "step_type")) - result_step = g.GetEdgeCost(parent, child, "step_type") - assert(result_step == expected_steps[child-1]) + # expected step types in format (parent, (child ids), (step types)) + expected_steps = ((0, (1,2,3,4), (3,1,2,2)), (4, (0,9,11,12), (3,3,1,2)), + (100, (67,143,144,145),(1,1,2,1)), + (200, (152,181,182,199,202,236,256,257), (3,3,2,1,1,2,1,2)), + (500, (431, 432, 489, 573), (1,1,1,1)), (750, (663,664, 841, 842), (1,1,1,1)), + (1000, (895, 896, 1111, 1112), (1,1,1,1)), + (1250, (1123,1124,1125,1249,1251,1388,1389,1390), (3,1,1,3,1,3,1,1)), + (1500, (1349,1350,1498,1499,1501,1663,1664,1665), (1,1,1,1,1,1,1,1)), + (2000, (1826,1827,1828,1999,2001,2179,2180,2181), (1,1,1,1,1,1,1,1)), + (3000, (2860,2861,2862,2999,3001,3103,3104,3105), (1,2,2,1,1,1,1,1))) + + for parent, children, expected_types in expected_steps: + for i in range(len(children)): + child = children[i] + print(parent, child) + expected_step_type = float(expected_types[i]) + result_step = g.GetEdgeCost(parent, child, "step_type") + assert(result_step == expected_step_type) From 0733da1f30596b91dc404cfa0909843dcf40dbb4 Mon Sep 17 00:00:00 2001 From: coliem Date: Mon, 27 Jan 2025 15:21:29 -0500 Subject: [PATCH 10/10] Clarified mapping between float and STEP types in step type query documentation. --- src/Python/dhart/graphgenerator/graph_generator.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Python/dhart/graphgenerator/graph_generator.py b/src/Python/dhart/graphgenerator/graph_generator.py index 2562f2b51..bf4babfbe 100644 --- a/src/Python/dhart/graphgenerator/graph_generator.py +++ b/src/Python/dhart/graphgenerator/graph_generator.py @@ -150,6 +150,17 @@ def CalculateAndStoreStepTypes( ) -> None: """Calculates and stores the step types of all edges in a given graph. It will be stored as cost type "step_type." + Notes: + The C++ code contains an internal mapping from a STEP struct to a float number for compatability purposes. + The mapping is as follows: + NOT_CONNECTED = 0, No connection between parent and child. + NONE = 1, Parent and child are on the same plane and no step is required. + UP = 2, A step up is required to get from parent to child. + DOWN = 3, A step down is required to get from parent to child. + OVER = 4 A step over something is required to get from parent to child. + In the example below, the step type between Node 0 and Node 1 is looked up and returns the value 3.0. This indicates + that the step type to get from node 0 to node 1 is "DOWN." + Args: g (Graph): Graph to query step types on. bvh (EmbreeBVH): Geometry to use for graph generation. The mesh used