1 // Copyright (c) 2017-2021, Lawrence Livermore National Security, LLC and
2 // other Axom Project Developers. See the top-level LICENSE file for details.
3 //
4 // SPDX-License-Identifier: (BSD-3-Clause)
5 
6 #ifndef AXOM_SPIN_LINEAR_BVH_VTKIO_HPP_
7 #define AXOM_SPIN_LINEAR_BVH_VTKIO_HPP_
8 
9 #include "axom/primal/geometry/BoundingBox.hpp"
10 
11 namespace axom
12 {
13 namespace spin
14 {
15 namespace internal
16 {
17 namespace linear_bvh
18 {
19 //------------------------------------------------------------------------------
20 template <typename FloatType>
write_box2d(const FloatType & xmin,const FloatType & ymin,const FloatType & xmax,const FloatType & ymax,int32 & numPoints,int32 & numBins,std::ostringstream & nodes,std::ostringstream & cells)21 void write_box2d(const FloatType& xmin,
22                  const FloatType& ymin,
23                  const FloatType& xmax,
24                  const FloatType& ymax,
25                  int32& numPoints,
26                  int32& numBins,
27                  std::ostringstream& nodes,
28                  std::ostringstream& cells)
29 {
30   nodes << xmin << " " << ymin << " 0.0\n";
31   nodes << xmax << " " << ymin << " 0.0\n";
32   nodes << xmax << " " << ymax << " 0.0\n";
33   nodes << xmin << " " << ymax << " 0.0\n";
34 
35   constexpr int32 NUM_NODES = 4;
36   int32 offset = numPoints;
37   cells << NUM_NODES << " ";
38   for(int32 i = 0; i < NUM_NODES; ++i)
39   {
40     cells << (offset + i) << " ";
41   }
42   cells << "\n";
43 
44   numBins += 1;
45   numPoints += NUM_NODES;
46 }
47 
48 //------------------------------------------------------------------------------
49 template <typename FloatType>
write_box3d(const FloatType & xmin,const FloatType & ymin,const FloatType & zmin,const FloatType & xmax,const FloatType & ymax,const FloatType & zmax,int32 & numPoints,int32 & numBins,std::ostringstream & nodes,std::ostringstream & cells)50 void write_box3d(const FloatType& xmin,
51                  const FloatType& ymin,
52                  const FloatType& zmin,
53                  const FloatType& xmax,
54                  const FloatType& ymax,
55                  const FloatType& zmax,
56                  int32& numPoints,
57                  int32& numBins,
58                  std::ostringstream& nodes,
59                  std::ostringstream& cells)
60 {
61   nodes << xmin << " " << ymin << " " << zmin << std::endl;
62   nodes << xmax << " " << ymin << " " << zmin << std::endl;
63   nodes << xmax << " " << ymax << " " << zmin << std::endl;
64   nodes << xmin << " " << ymax << " " << zmin << std::endl;
65 
66   nodes << xmin << " " << ymin << " " << zmax << std::endl;
67   nodes << xmax << " " << ymin << " " << zmax << std::endl;
68   nodes << xmax << " " << ymax << " " << zmax << std::endl;
69   nodes << xmin << " " << ymax << " " << zmax << std::endl;
70 
71   constexpr int32 NUM_NODES = 8;
72   int32 offset = numPoints;
73   cells << NUM_NODES << " ";
74   for(int32 i = 0; i < NUM_NODES; ++i)
75   {
76     cells << (offset + i) << " ";
77   }
78   cells << "\n";
79 
80   numBins += 1;
81   numPoints += NUM_NODES;
82 }
83 
84 //------------------------------------------------------------------------------
85 template <typename FloatType, int NDIMS>
write_box(const primal::BoundingBox<FloatType,NDIMS> & box,int32 & numPoints,int32 & numBins,std::ostringstream & nodes,std::ostringstream & cells)86 void write_box(const primal::BoundingBox<FloatType, NDIMS>& box,
87                int32& numPoints,
88                int32& numBins,
89                std::ostringstream& nodes,
90                std::ostringstream& cells)
91 {
92   const FloatType& xmin = box.getMin()[0];
93   const FloatType& ymin = box.getMin()[1];
94 
95   const FloatType& xmax = box.getMax()[0];
96   const FloatType& ymax = box.getMax()[1];
97 
98   if(NDIMS == 2)
99   {
100     write_box2d(xmin, ymin, xmax, ymax, numPoints, numBins, nodes, cells);
101   }
102   else
103   {
104     const FloatType& zmin = box.getMin()[2];
105     const FloatType& zmax = box.getMax()[2];
106 
107     write_box3d(xmin, ymin, zmin, xmax, ymax, zmax, numPoints, numBins, nodes, cells);
108   }
109 }
110 
111 //------------------------------------------------------------------------------
112 template <typename FloatType>
write_root(const primal::BoundingBox<FloatType,2> & root,int32 & numPoints,int32 & numBins,std::ostringstream & nodes,std::ostringstream & cells,std::ostringstream & levels)113 void write_root(const primal::BoundingBox<FloatType, 2>& root,
114                 int32& numPoints,
115                 int32& numBins,
116                 std::ostringstream& nodes,
117                 std::ostringstream& cells,
118                 std::ostringstream& levels)
119 {
120   write_box2d(root.getMin()[0],
121               root.getMin()[1],
122               root.getMax()[0],
123               root.getMax()[1],
124               numPoints,
125               numBins,
126               nodes,
127               cells);
128   levels << "0\n";
129 }
130 
131 //------------------------------------------------------------------------------
132 template <typename FloatType>
write_root(const primal::BoundingBox<FloatType,3> & root,int32 & numPoints,int32 & numBins,std::ostringstream & nodes,std::ostringstream & cells,std::ostringstream & levels)133 void write_root(const primal::BoundingBox<FloatType, 3>& root,
134                 int32& numPoints,
135                 int32& numBins,
136                 std::ostringstream& nodes,
137                 std::ostringstream& cells,
138                 std::ostringstream& levels)
139 {
140   write_box3d(root.getMin()[0],
141               root.getMin()[1],
142               root.getMin()[2],
143               root.getMax()[0],
144               root.getMax()[1],
145               root.getMax()[2],
146               numPoints,
147               numBins,
148               nodes,
149               cells);
150   levels << "0\n";
151 }
152 
153 //------------------------------------------------------------------------------
154 template <typename FloatType, int NDIMS>
write_recursive(primal::BoundingBox<FloatType,NDIMS> * inner_nodes,int32 * inner_node_children,int32 current_node,int32 level,int32 & numPoints,int32 & numBins,std::ostringstream & nodes,std::ostringstream & cells,std::ostringstream & levels)155 void write_recursive(primal::BoundingBox<FloatType, NDIMS>* inner_nodes,
156                      int32* inner_node_children,
157                      int32 current_node,
158                      int32 level,
159                      int32& numPoints,
160                      int32& numBins,
161                      std::ostringstream& nodes,
162                      std::ostringstream& cells,
163                      std::ostringstream& levels)
164 {
165   // STEP 0: get the flat BVH bounding boxes
166   primal::BoundingBox<FloatType, NDIMS> l_box = inner_nodes[current_node + 0];
167   primal::BoundingBox<FloatType, NDIMS> r_box = inner_nodes[current_node + 1];
168 
169   // STEP 1: extract children information
170   int32 l_child = inner_node_children[current_node + 0];
171   int32 r_child = inner_node_children[current_node + 1];
172 
173   write_box<FloatType, NDIMS>(l_box, numPoints, numBins, nodes, cells);
174   levels << level << std::endl;
175   write_box<FloatType, NDIMS>(r_box, numPoints, numBins, nodes, cells);
176   levels << level << std::endl;
177 
178   // STEP 2: check left
179   if(l_child > -1)
180   {
181     write_recursive<FloatType, NDIMS>(inner_nodes,
182                                       inner_node_children,
183                                       l_child,
184                                       level + 1,
185                                       numPoints,
186                                       numBins,
187                                       nodes,
188                                       cells,
189                                       levels);
190   }
191 
192   // STEP 3: check right
193   if(r_child > -1)
194   {
195     write_recursive<FloatType, NDIMS>(inner_nodes,
196                                       inner_node_children,
197                                       r_child,
198                                       level + 1,
199                                       numPoints,
200                                       numBins,
201                                       nodes,
202                                       cells,
203                                       levels);
204   }
205 }
206 
207 } /* namespace linear_bvh */
208 } /* namespace internal */
209 } /* namespace spin */
210 } /* namespace axom */
211 
212 #endif /* AXOM_SPIN_LINEAR_BVH_VTKIO_HPP_ */
213