1 // This is brl/bbas/bmsh3d/vis/bmsh3d_vis_utils.cxx
2 #include <iostream>
3 #include <vector>
4 #include "bmsh3d_vis_utils.h"
5 //:
6 // \file
7 // \author MingChing Chang
8 // \date May 03, 2005.
9 
10 #ifdef _MSC_VER
11 #  include "vcl_msvc_warnings.h"
12 #endif
13 #include <cassert>
14 #include "vnl/vnl_random.h"
15 #include "vnl/vnl_math.h"
16 #include "vgl/vgl_vector_3d.h"
17 
18 #include <Inventor/nodes/SoSeparator.h>
19 #include <Inventor/nodes/SoBaseColor.h>
20 #include <Inventor/nodes/SoDrawStyle.h>
21 #include <Inventor/nodes/SoCoordinate3.h>
22 #include <Inventor/nodes/SoMaterial.h>
23 #include <Inventor/nodes/SoVertexProperty.h>
24 #include <Inventor/nodes/SoIndexedFaceSet.h>
25 #include <Inventor/nodes/SoIndexedLineSet.h>
26 #include <Inventor/nodes/SoShapeHints.h>
27 #include <Inventor/nodes/SoText2.h>
28 #include <Inventor/nodes/SoTransform.h>
29 #include <Inventor/nodes/SoTranslation.h>
30 #include <Inventor/nodes/SoRotation.h>
31 #include <Inventor/nodes/SoPointSet.h>
32 #include <Inventor/nodes/SoCube.h>
33 #include <Inventor/nodes/SoSphere.h>
34 #include <Inventor/nodes/SoCylinder.h>
35 #include <Inventor/nodes/SoLineSet.h>
36 #include <Inventor/nodes/SoFaceSet.h>
37 #include <Inventor/nodes/SoDirectionalLight.h>
38 #include <Inventor/actions/SoSearchAction.h>
39 
color_from_code(const int colorcode)40 SbColor color_from_code (const int colorcode)
41 {
42   switch (colorcode)
43   {
44    case COLOR_NOT_SPECIFIED:return SbColor(0.5f, 0.5f, 0.5f);
45    case COLOR_BLACK:     return SbColor(0.0f, 0.0f, 0.0f);
46    case COLOR_RED:       return SbColor(1.0f, 0.0f, 0.0f);
47    case COLOR_GREEN:     return SbColor(0.0f, 1.0f, 0.0f);
48    case COLOR_BLUE:      return SbColor(0.0f, 0.0f, 1.0f);
49    case COLOR_YELLOW:    return SbColor(1.0f, 1.0f, 0.0f);
50    case COLOR_CYAN:      return SbColor(0.0f, 1.0f, 1.0f);
51    case COLOR_PINK:      return SbColor(1.0f, 0.0f, 1.0f);
52    case COLOR_GRAY:      return SbColor(0.6f, 0.6f, 0.6f);
53    case COLOR_DARKGRAY:  return SbColor(0.4f, 0.4f, 0.4f);
54    case COLOR_DARKRED:   return SbColor(0.5f, 0.0f, 0.0f);
55    case COLOR_DARKGREEN: return SbColor(0.0f, 0.5f, 0.0f);
56    case COLOR_DARKBLUE:  return SbColor(0.0f, 0.0f, 0.5f);
57    case COLOR_DARKYELLOW:return SbColor(0.5f, 0.5f, 0.0f);
58    case COLOR_DARKCYAN:  return SbColor(0.0f, 0.5f, 0.5f);
59    case COLOR_PURPLE:    return SbColor(0.5f, 0.0f, 0.5f);
60    case COLOR_WHITE:     return SbColor(1.0f, 1.0f, 1.0f);
61    case COLOR_LIGHTGRAY: return SbColor(0.6f, 0.6f, 0.6f);
62    case COLOR_GRAYBLUE:  return SbColor(0.5f, 0.5f, 1.0f);
63    case COLOR_LIGHTGREEN:return SbColor(0.5f, 1.0f, 0.5f);
64    case COLOR_ORANGE:    return SbColor(1.0f, 0.7f, 0.0f);
65    case COLOR_GOLD:      return SbColor(0.8f, 0.7f, 0.2f);
66    case COLOR_SILVER:    return SbColor(0.8f, 0.8f, 0.8f);
67    case COLOR_RANDOM:    return get_next_rand_color();
68    default: assert(0);   return SbColor(0.0f, 0.0f, 0.0f);
69   }
70 
71   return SbColor (0.0f, 0.0f, 0.0f);
72 }
73 
74 //: The scenegraph getParent function.
75 //  See http://doc.coin3d.org/Coin/classSoGroup.html
getParent(SoNode * node,SoNode * root)76 SoGroup* getParent (SoNode* node, SoNode* root)
77 {
78   SoSearchAction sa;
79   sa.setNode(node);
80   sa.setInterest(SoSearchAction::FIRST);
81   sa.apply(root);
82   SoPath * p = sa.getPath();
83   assert(p && "getPath() not found");
84   if (p->getLength() < 2) {
85     return NULL;
86   } // no parent
87   return (SoGroup *) p->getNodeFromTail(1);
88 }
89 
assign_rgb_light(SoSeparator * root)90 void assign_rgb_light (SoSeparator* root)
91 {
92   SoDirectionalLight* light1 = new SoDirectionalLight;
93   light1->direction = SbVec3f(1,0,0);
94   light1->color = SbColor(0.5,0,0);
95   root->addChild (light1);
96 
97   SoDirectionalLight* light2 = new SoDirectionalLight;
98   light2->direction = SbVec3f(0,1,0);
99   light2->color = SbColor(0,0.5,0);
100   root->addChild (light2);
101 
102   SoDirectionalLight* light3 = new SoDirectionalLight;
103   light3->direction = SbVec3f(0,0,1);
104   light3->color = SbColor(0,0,0.5);
105   root->addChild (light3);
106 
107   SoDirectionalLight* light4 = new SoDirectionalLight;
108   light4->direction = SbVec3f(-1,0,0);
109   light4->color = SbColor(0.5,0,0);
110   root->addChild (light4);
111 
112   SoDirectionalLight* light5 = new SoDirectionalLight;
113   light5->direction = SbVec3f(0,-1,0);
114   light5->color = SbColor(0,0.5,0);
115   root->addChild (light5);
116 
117   SoDirectionalLight* light6 = new SoDirectionalLight;
118   light6->direction = SbVec3f(0,0,-1);
119   light6->color = SbColor(0,0,0.5);
120   root->addChild (light6);
121 }
122 
123 // cvalue 0: blue, cvalue 1: red
get_color_tone(float cvalue)124 SbColor get_color_tone (float cvalue)
125 {
126   SbColor color;
127 
128   if (cvalue < 0.25f)      // From Blue to Aqua
129     color = SbColor (0.0f, cvalue*4, 1.0f);
130   else if (cvalue < 0.5f)  // From Aqua to Green
131     color = SbColor (0.0f, 1.0f, (0.5f-cvalue)*4);
132   else if (cvalue < 0.75f) // From Green to Yellow
133     color = SbColor ((cvalue-0.5f)*4, 1.0f, 0.0f);
134   else                     // From Yellow to Red
135     color = SbColor (1.0f, (1.0f-cvalue)*4, 0.0f);
136 
137   return color;
138 }
139 
generate_color_table(unsigned long seed,unsigned int size,std::vector<SbColor> & color_table)140 void generate_color_table (unsigned long seed, unsigned int size,
141                            std::vector<SbColor>& color_table)
142 {
143   color_table.clear();
144 
145   //: initialize the random color by given seed
146   init_rand_color (seed);
147 
148   for (unsigned int i=0; i<size; i++) {
149     //: generate a random color and store it
150     SbColor color = get_next_rand_color ();
151     color_table.push_back (color);
152   }
153 }
154 
155 // #######################################################
156 
draw_cube_geom(const float x,const float y,const float z,const float size)157 SoSeparator* draw_cube_geom (const float x, const float y, const float z,
158                              const float size)
159 {
160   SoSeparator* root = new SoSeparator;
161 
162   SoTranslation* trans = new SoTranslation;
163   trans->translation.setValue (SbVec3f(x, y, z));
164   root->addChild (trans);
165 
166   SoCube* cube = new SoCube ();
167   cube->width = size;
168   cube->height = size;
169   cube->depth = size;
170   root->addChild (cube);
171 
172   return root;
173 }
174 
draw_cube_geom(const vgl_point_3d<double> pt,const float size)175 SoSeparator* draw_cube_geom (const vgl_point_3d<double> pt, const float size)
176 {
177   return draw_cube_geom ((float)pt.x(), (float)pt.y(), (float)pt.z(), size);
178 }
179 
draw_cube(const float x,const float y,const float z,const float size,const SbColor & color)180 SoSeparator* draw_cube (const float x, const float y, const float z,
181                         const float size, const SbColor& color)
182 {
183   SoSeparator* root = new SoSeparator;
184 
185   // color
186   SoBaseColor *basecolor = new SoBaseColor;
187   basecolor->rgb = color;
188   root->addChild (basecolor);
189 
190   SoTranslation* trans = new SoTranslation;
191   trans->translation.setValue (SbVec3f(x, y, z));
192   root->addChild (trans);
193 
194   SoCube* cube = new SoCube ();
195   cube->width = size;
196   cube->height = size;
197   cube->depth = size;
198   root->addChild (cube);
199 
200   return root;
201 }
202 
draw_cube(const vgl_point_3d<double> pt,const float size,const SbColor & color)203 SoSeparator* draw_cube (const vgl_point_3d<double> pt,
204                         const float size, const SbColor& color)
205 {
206   return draw_cube ((float)pt.x(), (float)pt.y(), (float)pt.z(), size, color);
207 }
208 
draw_sphere_geom(const float x,const float y,const float z,const float radius)209 SoSeparator* draw_sphere_geom (const float x, const float y, const float z,
210                                const float radius)
211 {
212   SoSeparator* root = new SoSeparator;
213 
214   SoTranslation* trans = new SoTranslation;
215   trans->translation.setValue (SbVec3f(x, y, z));
216   root->addChild (trans);
217 
218   SoSphere* sphere = new SoSphere ();
219   sphere->radius = radius;
220   root->addChild (sphere);
221 
222   return root;
223 }
224 
draw_sphere_geom(const vgl_point_3d<double> pt,const float radius)225 SoSeparator* draw_sphere_geom (const vgl_point_3d<double> pt, const float radius)
226 {
227   return draw_sphere_geom ((float)pt.x(), (float)pt.y(), (float)pt.z(), radius);
228 }
229 
draw_sphere(const float x,const float y,const float z,const float radius,const SbColor & color)230 SoSeparator* draw_sphere (const float x, const float y, const float z,
231                           const float radius, const SbColor& color)
232 {
233   SoSeparator* root = new SoSeparator;
234 
235   SoBaseColor *basecolor = new SoBaseColor;
236   basecolor->rgb = color;
237   root->addChild (basecolor);
238 
239   SoTranslation* trans = new SoTranslation;
240   trans->translation.setValue (SbVec3f(x, y, z));
241   root->addChild (trans);
242 
243   SoSphere* sphere = new SoSphere ();
244   sphere->radius = radius;
245   root->addChild (sphere);
246 
247   return root;
248 }
249 
draw_sphere(const vgl_point_3d<double> pt,const float radius,const SbColor & color)250 SoSeparator* draw_sphere (const vgl_point_3d<double> pt,
251                           const float radius, const SbColor& color)
252 {
253   return draw_sphere ((float)pt.x(), (float)pt.y(), (float)pt.z(), radius, color);
254 }
255 
256 
257 //: draw a cylinder, given the radius, the coordinates of the start and end points of the centerline
draw_cylinder(float x1,float y1,float z1,float x2,float y2,float z2,float radius,const SbColor & color,float transparency)258 SoSeparator* draw_cylinder(float x1, float y1, float z1,
259                            float x2, float y2, float z2,
260                            float radius,
261                            const SbColor& color,
262                            float transparency)
263 {
264   SoSeparator* root = new SoSeparator;
265 #if 0
266   // color
267   SoBaseColor *basecolor = new SoBaseColor;
268   basecolor->rgb = color;
269   root->addChild (basecolor);
270 #endif // 0
271   // Create a SoMaterial to draw color in detail.
272   SoMaterial *material = new SoMaterial;
273   material->diffuseColor.setValue (color);
274   material->emissiveColor.setValue(color/2);
275   material->transparency = transparency;
276   root->addChild (material);
277 
278   // translation
279   SoTranslation* trans = new SoTranslation;
280   trans->translation.setValue (SbVec3f(x1, y1, z1));
281   root->addChild (trans);
282 
283   // rotaiton
284   SoRotation* rot = new SoRotation;
285 
286   vgl_vector_3d<float > y_axis(0, 1, 0);
287   vgl_vector_3d<float > cylinder_orient(x2-x1, y2-y1, z2-z1);
288   vgl_vector_3d<float > rot_axis = cross_product(y_axis, cylinder_orient);
289   float rot_angle = (float)angle(y_axis, cylinder_orient);
290 
291   rot->rotation.setValue(SbVec3f(rot_axis.x(), rot_axis.y(), rot_axis.z()), rot_angle);
292   root->addChild (rot);
293 
294   SoCylinder* cylinder = new SoCylinder();
295   cylinder->radius = radius;
296   cylinder->height = std::sqrt(vnl_math::sqr(x2-x1) +
297                               vnl_math::sqr(y2-y1) +
298                               vnl_math::sqr(z2-z1));
299 
300   root->addChild(cylinder);
301   return root;
302 }
303 
draw_cylinder(const vgl_point_3d<double> & centerline_start,const vgl_point_3d<double> & centerline_end,float radius,const SbColor & color,float transparency)304 SoSeparator* draw_cylinder(const vgl_point_3d<double>& centerline_start,
305                            const vgl_point_3d<double>& centerline_end,
306                            float radius,
307                            const SbColor& color,
308                            float transparency)
309 {
310   return draw_cylinder((float)centerline_start.x(), (float)centerline_start.y(),
311                        (float)centerline_start.z(), (float)centerline_end.x(),
312                        (float)centerline_end.y(), (float)centerline_end.z(),
313                        radius,
314                        color,
315                        transparency);
316 }
317 
318 
319 //:
320 // Important:
321 //  Should use the draw_geometry to draw group of things for
322 //  better performance.
323 
draw_polyline(std::vector<vgl_point_3d<double>> & vertices,const float & width,const SbColor & color)324 SoSeparator* draw_polyline (std::vector<vgl_point_3d<double> >& vertices,
325                             const float& width, const SbColor& color)
326 {
327   SoSeparator* root = new SoSeparator;
328 
329   SoBaseColor *basecolor = new SoBaseColor;
330   basecolor->rgb = color;
331   root->addChild (basecolor);
332 
333   // Line width
334   SoDrawStyle*  drawStyle = new SoDrawStyle;
335   drawStyle->lineWidth.setValue (width);
336   root->addChild (drawStyle);
337 
338   draw_polyline_geom (root, vertices);
339 
340   return root;
341 }
342 
draw_polyline_geom(SoGroup * root,std::vector<vgl_point_3d<double>> & vertices)343 void draw_polyline_geom (SoGroup *root, std::vector<vgl_point_3d<double> >& vertices)
344 {
345   unsigned int nVertices = vertices.size();
346   SbVec3f* verts = new SbVec3f[nVertices];
347 
348   for (unsigned int i=0; i<nVertices; i++) {
349     vgl_point_3d<double> p = vertices[i];
350     verts[i] = SbVec3f( (float)p.x(), (float)p.y(), (float)p.z() );
351   }
352 
353   SoCoordinate3* coords = new SoCoordinate3;
354   coords->point.setValues (0, nVertices, verts);
355   root->addChild (coords);
356 
357   SoLineSet* lineSet = new SoLineSet;
358   lineSet->numVertices.set1Value (0, nVertices);
359   root->addChild (lineSet);
360 
361   delete[] verts;
362 }
363 
364 // draws a polyline with the specified color and drawstyle
draw_polyline(const float ** vertices,const unsigned int nVertices,const SbColor & color,const SoDrawStyle * drawStyle)365 SoSeparator* draw_polyline (const float** vertices, const unsigned int nVertices,
366                             const SbColor& color, const SoDrawStyle* drawStyle)
367 {
368   SoSeparator* root = new SoSeparator;
369 
370   SoBaseColor *basecolor = new SoBaseColor;
371   basecolor->rgb = color;
372   root->addChild (basecolor);
373 
374   // Line width
375   root->addChild ((SoDrawStyle*) drawStyle); // casting away const !!!
376 
377   SbVec3f* verts = new SbVec3f[nVertices];
378   for (unsigned int i=0; i<nVertices; i++)
379     verts[i] = SbVec3f( vertices[i][0], vertices[i][1], vertices[i][2] );
380 
381   draw_polyline_geom (root, verts, nVertices);
382 
383   delete[] verts;
384 
385   return root;
386 }
387 
388 // draws a single polyline with no special properties
draw_polyline_geom(SoGroup * root,SbVec3f * vertices,const unsigned int nVertices)389 void draw_polyline_geom (SoGroup* root, SbVec3f* vertices, const unsigned int nVertices)
390 {
391   SoCoordinate3* coords = new SoCoordinate3;
392   coords->point.setValues (0, nVertices, vertices);
393   root->addChild (coords);
394 
395   SoLineSet* lineSet = new SoLineSet;
396   lineSet->numVertices.set1Value (0, nVertices);
397   root->addChild (lineSet);
398 }
399 
400 
draw_filled_polygon_geom_(SoGroup * root,const std::vector<bmsh3d_vertex * > & vertices)401 void draw_filled_polygon_geom_ (SoGroup* root, const std::vector<bmsh3d_vertex*>& vertices)
402 {
403   SbVec3f* verts = new SbVec3f[vertices.size()];
404   for (unsigned int i=0; i<vertices.size(); i++)
405     verts[i] = SbVec3f(float(vertices[i]->pt().x()), float(vertices[i]->pt().y()), float(vertices[i]->pt().z()));
406 
407   draw_filled_polygon_geom_ (root, verts, vertices.size());
408 
409   delete[] verts;
410 }
411 
412 //:
413 //  Ming: We have two options to draw the IndexedFaceSet.
414 //  Option 1: make the emissiveColor the same as diffuseColor
415 //            The sheet will look continuously.
416 //  Option 2: make the emissiveColor half value of diffuseColor (color/2)
417 //            to show individual sheet elements.
418 // draws a polygon with the specified color, drawstyle and transparency
419 
draw_filled_polygon(SbVec3f * vertices,const unsigned int nVertices,const SbColor & color,const float fTransparency)420 SoSeparator* draw_filled_polygon (SbVec3f* vertices, const unsigned int nVertices,
421                                   const SbColor& color, const float fTransparency)
422 {
423   SoSeparator* root = new SoSeparator;
424 
425   // Create a SoMaterial to draw color in detail.
426   SoMaterial *material = new SoMaterial;
427   material->diffuseColor.setValue (color);
428   material->emissiveColor.setValue(color/2);
429   material->transparency = fTransparency;
430   root->addChild (material);
431 
432   draw_filled_polygon_geom_ (root, vertices, nVertices);
433 
434   return root;
435 }
436 
draw_filled_polygon(float ** vertices,const unsigned int nVertices,const SbColor & color,const float fTransparency)437 SoSeparator* draw_filled_polygon (float** vertices, const unsigned int nVertices,
438                                   const SbColor& color, const float fTransparency)
439 {
440   SoSeparator* root = new SoSeparator;
441 
442   // Create a SoMaterial to draw color in detail.
443   SoMaterial *material = new SoMaterial;
444   material->diffuseColor.setValue (color);
445   material->emissiveColor.setValue(color/2);
446   material->transparency = fTransparency;
447   root->addChild (material);
448 
449   SbVec3f* verts = new SbVec3f[nVertices];
450   for (unsigned int i=0; i<nVertices; i++)
451     verts[i] = SbVec3f (vertices[i][0], vertices[i][1], vertices[i][2]);
452 
453   draw_filled_polygon_geom_ (root, verts, nVertices);
454 
455   delete[] verts;
456   return root;
457 }
458 
459 // draw a simple filled polygon with no special properties
draw_filled_polygon_geom_(SoGroup * root,SbVec3f * vertices,const unsigned int nVertices)460 void draw_filled_polygon_geom_ (SoGroup* root, SbVec3f* vertices, const unsigned int nVertices)
461 {
462   SoCoordinate3* coords = new SoCoordinate3;
463   coords->point.setValues (0, nVertices, vertices);
464   root->addChild (coords);
465 
466   SoFaceSet* faceSet = new SoFaceSet;
467   faceSet->numVertices.set1Value (0, nVertices);
468   root->addChild (faceSet);
469 }
470 
draw_line_set(const std::vector<std::pair<vgl_point_3d<double>,vgl_point_3d<double>>> & lines,const SbColor & color)471 SoSeparator* draw_line_set (const std::vector<std::pair<vgl_point_3d<double>, vgl_point_3d<double> > >& lines,
472                             const SbColor& color)
473 {
474   SoSeparator* root = new SoSeparator;
475   // color
476   SoBaseColor* basecolor = new SoBaseColor;
477   basecolor->rgb = color;
478   root->addChild (basecolor);
479 
480   draw_line_set_geom (root, lines);
481 
482   return root;
483 }
484 
485 //: draw the whole set of lines in a single SoIndexedLineSet.
draw_line_set_geom(SoSeparator * root,const std::vector<std::pair<vgl_point_3d<double>,vgl_point_3d<double>>> & lines)486 void draw_line_set_geom(SoSeparator* root,
487                         const std::vector<std::pair<vgl_point_3d<double>, vgl_point_3d<double> > >& lines)
488 {
489   unsigned int nVertices = lines.size() * 2;
490   float (*xyz)[3] = new float[nVertices][3];
491   unsigned int nLinesIndices = lines.size() * 3; // sid : eid : -1
492   int* ind = new int [nLinesIndices];
493 
494   // Assign vertices and lines
495   for (unsigned int i=0; i < lines.size(); i++) {
496     vgl_point_3d<double> Ps = lines[i].first;
497     vgl_point_3d<double> Pe = lines[i].second;
498     xyz[i*2][0] = (float) Ps.x();
499     xyz[i*2][1] = (float) Ps.y();
500     xyz[i*2][2] = (float) Ps.z();
501     xyz[i*2+1][0] = (float) Pe.x();
502     xyz[i*2+1][1] = (float) Pe.y();
503     xyz[i*2+1][2] = (float) Pe.z();
504     ind[i*3] = i*2;
505     ind[i*3+1] = i*2+1;
506     ind[i*3+2] = -1;
507   }
508 
509   SoVertexProperty* vp = new SoVertexProperty;
510   vp->vertex.setValues (0, nVertices, xyz);
511 
512   SoIndexedLineSet* indexedLineSet = new SoIndexedLineSet ();
513   indexedLineSet->vertexProperty = vp;
514   indexedLineSet->coordIndex.setValues (0, nLinesIndices, ind);
515 
516   delete []ind;
517   delete []xyz;
518 
519   root->addChild (indexedLineSet);
520 }
521 
draw_triangle_geom(SoGroup * root,const vgl_point_3d<double> & Pt1,const vgl_point_3d<double> & Pt2,const vgl_point_3d<double> & Pt3)522 void draw_triangle_geom (SoGroup* root,
523                          const vgl_point_3d<double>& Pt1,
524                          const vgl_point_3d<double>& Pt2,
525                          const vgl_point_3d<double>& Pt3)
526 {
527   SoCoordinate3* coords = new SoCoordinate3;
528   coords->point.set1Value( 0, SbVec3f( (float)Pt1.x(), (float)Pt1.y(), (float)Pt1.z()) );
529   coords->point.set1Value( 1, SbVec3f( (float)Pt2.x(), (float)Pt2.y(), (float)Pt2.z()) );
530   coords->point.set1Value( 2, SbVec3f( (float)Pt3.x(), (float)Pt3.y(), (float)Pt3.z()) );
531   root->addChild(coords);
532 
533   SoFaceSet* faceSet = new SoFaceSet;
534   faceSet->numVertices.set1Value(0,3);
535   root->addChild(faceSet);
536 }
537 
538 // draws a single triangle with no special properties
draw_triangle_geom(SoGroup * root,const float x1,const float y1,const float z1,const float x2,const float y2,const float z2,const float x3,const float y3,const float z3)539 void draw_triangle_geom (SoGroup *root,
540                          const float x1, const float y1, const float z1,
541                          const float x2, const float y2, const float z2,
542                          const float x3, const float y3, const float z3)
543 {
544   SoCoordinate3* coords = new SoCoordinate3;
545   coords->point.set1Value(0,SbVec3f(x1,y1,z1));
546   coords->point.set1Value(1,SbVec3f(x2,y2,z2));
547   coords->point.set1Value(2,SbVec3f(x3,y3,z3));
548   root->addChild(coords);
549 
550   SoFaceSet* faceSet = new SoFaceSet;
551   faceSet->numVertices.set1Value(0,3);
552   root->addChild(faceSet);
553 }
554 
555 // draws a line with the specified color and drawstyle
draw_line(const float x1,const float y1,const float z1,const float x2,const float y2,const float z2,const SbColor & color,const SoDrawStyle * drawStyle)556 SoSeparator* draw_line (const float x1, const float y1, const float z1,
557                         const float x2, const float y2, const float z2,
558                         const SbColor& color, const SoDrawStyle* drawStyle)
559 {
560   SoSeparator* root = new SoSeparator;
561 
562   // color
563   SoBaseColor *basecolor = new SoBaseColor;
564   basecolor->rgb = color;
565   root->addChild (basecolor);
566 
567   if (drawStyle)
568     root->addChild ((SoDrawStyle*) drawStyle); // casting away const !!!
569 
570   draw_line_geom (root, x1, y1, z1, x2, y2, z2);
571   return root;
572 }
573 
574 // draws a line with the specified color and drawstyle
draw_line(const vgl_point_3d<double> & pt1,const vgl_point_3d<double> & pt2,const SbColor & color,const SoDrawStyle * drawStyle)575 SoSeparator* draw_line (const vgl_point_3d<double>& pt1, const vgl_point_3d<double>& pt2,
576                         const SbColor& color, const SoDrawStyle* drawStyle)
577 {
578   return draw_line ((float)pt1.x(), (float)pt1.y(), (float)pt1.z(),
579                     (float)pt2.x(), (float)pt2.y(), (float)pt2.z(), color, drawStyle);
580 }
581 
582 // draws a single line with no special properties
draw_line_geom(SoGroup * root,const float x1,const float y1,const float z1,const float x2,const float y2,const float z2)583 void draw_line_geom (SoGroup* root,
584                      const float x1, const float y1, const float z1,
585                      const float x2, const float y2, const float z2)
586 {
587   SoCoordinate3* coord = new SoCoordinate3;
588   coord->point.set1Value(0, SbVec3f( x1,y1,z1 ) );
589   coord->point.set1Value(1, SbVec3f( x2,y2,z2 ) );
590   root->addChild( coord );
591 
592   SoLineSet* lineSet = new SoLineSet;
593   lineSet->numVertices.set1Value( 0, 2 );
594   root->addChild( lineSet );
595 }
596 
draw_line_geom(SoGroup * root,const vgl_point_3d<double> & pt1,const vgl_point_3d<double> & pt2)597 void draw_line_geom (SoGroup* root, const vgl_point_3d<double>& pt1, const vgl_point_3d<double>& pt2)
598 {
599   draw_line_geom (root,
600                   (float)pt1.x(), (float)pt1.y(), (float)pt1.z(),
601                   (float)pt2.x(), (float)pt2.y(), (float)pt2.z());
602 }
603 
draw_text2d(const char * text,const float x,const float y,const float z)604 SoSeparator* draw_text2d (const char* text,
605                           const float x, const float y, const float z)
606 {
607   SoSeparator* root = new SoSeparator;
608 
609   SoTransform *instrTransf = new SoTransform;
610   instrTransf->translation.setValue (x, y, z);
611   root->addChild(instrTransf);
612 
613   draw_text2d_geom (root, text);
614 
615   return root;
616 }
617 
draw_box(const double & min_x,const double & min_y,const double & min_z,const double & max_x,const double & max_y,const double & max_z,const float & width,const SbColor & color)618 SoSeparator* draw_box (const double& min_x, const double& min_y, const double& min_z,
619                        const double& max_x, const double& max_y, const double& max_z,
620                        const float& width, const SbColor& color)
621 {
622   SoSeparator* root = new SoSeparator;
623 
624   // color
625   SoBaseColor* basecolor = new SoBaseColor;
626   basecolor->rgb = color;
627   root->addChild (basecolor);
628 
629   SoDrawStyle* drawStyle = new SoDrawStyle;
630   drawStyle->lineWidth.setValue (width);
631   root->addChild (drawStyle);
632 
633   // side parallel to X
634   draw_line_geom (root, (float)min_x, (float)min_y, (float)min_z, (float)max_x, (float)min_y, (float)min_z);
635   draw_line_geom (root, (float)min_x, (float)min_y, (float)max_z, (float)max_x, (float)min_y, (float)max_z);
636   draw_line_geom (root, (float)min_x, (float)max_y, (float)min_z, (float)max_x, (float)max_y, (float)min_z);
637   draw_line_geom (root, (float)min_x, (float)max_y, (float)max_z, (float)max_x, (float)max_y, (float)max_z);
638 
639   // side parallel to Y
640   draw_line_geom (root, (float)min_x, (float)min_y, (float)min_z, (float)min_x, (float)max_y, (float)min_z);
641   draw_line_geom (root, (float)min_x, (float)min_y, (float)max_z, (float)min_x, (float)max_y, (float)max_z);
642   draw_line_geom (root, (float)max_x, (float)min_y, (float)min_z, (float)max_x, (float)max_y, (float)min_z);
643   draw_line_geom (root, (float)max_x, (float)min_y, (float)max_z, (float)max_x, (float)max_y, (float)max_z);
644 
645   // side parallel to Z
646   draw_line_geom (root, (float)min_x, (float)min_y, (float)min_z, (float)min_x, (float)min_y, (float)max_z);
647   draw_line_geom (root, (float)min_x, (float)max_y, (float)min_z, (float)min_x, (float)max_y, (float)max_z);
648   draw_line_geom (root, (float)max_x, (float)min_y, (float)min_z, (float)max_x, (float)min_y, (float)max_z);
649   draw_line_geom (root, (float)max_x, (float)max_y, (float)min_z, (float)max_x, (float)max_y, (float)max_z);
650 
651   return root;
652 }
653 
draw_box(const vgl_box_3d<double> & box,const float & width,const SbColor & color)654 SoSeparator* draw_box (const vgl_box_3d<double>& box,
655                        const float& width, const SbColor& color)
656 {
657   return draw_box (box.min_x(), box.min_y(), box.min_z(),
658                    box.max_x(), box.max_y(), box.max_z(),
659                    width, color);
660 }
661 
draw_text2d(const char * text,const float x,const float y,const float z,const SoBaseColor * basecolor)662 SoSeparator* draw_text2d (const char* text,
663                           const float x, const float y, const float z,
664                           const SoBaseColor* basecolor)
665 {
666   SoSeparator* root = new SoSeparator;
667 
668   SoTransform *instrTransf = new SoTransform;
669   instrTransf->translation.setValue (x, y, z);
670   root->addChild(instrTransf);
671 
672   // basecolor
673   root->addChild ((SoBaseColor*) basecolor); // casting away const !!!
674 
675   draw_text2d_geom (root, text);
676 
677   return root;
678 }
679 
draw_text2d_geom(SoSeparator * root,const char * text)680 void draw_text2d_geom (SoSeparator* root, const char* text)
681 {
682   SoText2 * text2 = new SoText2;
683   SbString txt = SbString (text);
684   text2->string.setValues (0, sizeof(text) / sizeof(char *), &txt);
685   text2->justification = SoText2::LEFT;
686   root->addChild(text2);
687 }
688 
689 // ############################################################
690 
691 vnl_random colrand;
692 
init_rand_color(unsigned long seed)693 void init_rand_color (unsigned long seed)
694 {
695   colrand.reseed (seed);
696 }
697 
get_next_rand_ccode()698 VIS_COLOR_CODE get_next_rand_ccode ()
699 {
700   double c = colrand.drand32 (1, COLOR_ORANGE);
701   return (VIS_COLOR_CODE) int (c);
702 }
703 
get_next_rand_color()704 SbColor get_next_rand_color ()
705 {
706   float r = (float) colrand.drand32 (0, 1);
707   float g = (float) colrand.drand32 (0, 1);
708   float b = (float) colrand.drand32 (0, 1);
709 
710   SbColor color = SbColor (r, g, b);
711 
712   return color;
713 }
714 
shift_output(SoSeparator * vis,float shift_x,float shift_y,float shift_z)715 SoSeparator* shift_output (SoSeparator* vis, float shift_x, float shift_y, float shift_z)
716 {
717   SoSeparator* trans_group = new SoSeparator;
718   SoTranslation *trans = new SoTranslation;
719   trans->translation.setValue (SbVec3f (shift_x, shift_y, shift_z));
720   trans_group->addChild (trans);
721   trans_group->addChild (vis);
722   return trans_group;
723 }
724 
725 // ##################################################################
726 
727 #if 0
728 
729 void draw_point_test (SoSeparator* root)
730 {
731   constexpr int NUMPOINTS = 5000;
732   float xyz[NUMPOINTS][3];
733 
734   for (int i=0; i < NUMPOINTS; i++) {
735     xyz[i][0] = (float)rand() / (float)RAND_MAX * 10;
736     xyz[i][1] = (float)rand() / (float)RAND_MAX * 10;
737     xyz[i][2] = (float)rand() / (float)RAND_MAX * 10;
738   }
739 
740   SoCoordinate3 * coord3 = new SoCoordinate3;
741   coord3->point.setValues(0, NUMPOINTS, xyz);
742   root->addChild(coord3);
743 
744   SoDrawStyle * drawstyle = new SoDrawStyle;
745   drawstyle->pointSize = 1;
746   root->addChild(drawstyle);
747 
748   SoPointSet * pointset = new SoPointSet;
749   root->addChild(pointset);
750 }
751 
752 void draw_text_test (SoSeparator* root)
753 {
754   SoText2 * text = new SoText2;
755 
756   const char * str[] = {
757     "Yo Yo Yo. 2D Text is working!",
758     "LEMS Brown University",
759     "1 2 3 4 5 6 7 8 9 10.",
760   };
761 
762   text->string.setValues(0, sizeof(str) / sizeof(char *), str);
763   text->justification = SoText2::LEFT;
764   SoTransform *instrTransf = new SoTransform;
765   instrTransf->translation.setValue(-1.0f,5.0f,0.0f);
766   root->addChild(instrTransf);
767   root->addChild(text);
768 }
769 
770 void draw_polyline_test (SoSeparator* root)
771 {
772   // Points in N*3 float array.
773   SoVertexProperty *vertexList = new SoVertexProperty();
774   root->addChild(vertexList);
775 
776   int N = 3;
777 #if 0
778   for (int i=0; i<N; i++)
779     vertexList->vertex.set1Value (i, 1.2*i, 1.3*i*i, 1.4*i);
780 #endif // 0
781   vertexList->vertex.set1Value (0, 0, 0, 0);
782   vertexList->vertex.set1Value (1, 1, 1, 1);
783   vertexList->vertex.set1Value (2, 5, 1, 1);
784 
785   // Line
786   int N_LINE = N-1;
787   int *lineindex = new int[N_LINE*3];
788   for (int i=0; i<N_LINE; i++) {
789     lineindex[i*3] = i;
790     lineindex[i*3+1] = i+1;
791     lineindex[i*3+2] = -1;
792   }
793 
794   SoIndexedLineSet *vertIndex = new SoIndexedLineSet();
795   vertIndex->coordIndex.setValues (0, N_LINE*3, lineindex);
796   root->addChild(vertIndex);
797 
798   delete[] lineindex;
799 }
800 
801 void draw_polygon_test (SoSeparator* root)
802 {
803   // Points in N*3 float array.
804   SoVertexProperty *vertexList = new SoVertexProperty();
805   root->addChild(vertexList);
806 
807   int N = 3;
808 #if 0
809   for (int i=0; i<N; i++)
810     vertexList->vertex.set1Value (i, 1.2*i, 1.3*i*i, 1.4*i);
811 #endif // 0
812   vertexList->vertex.set1Value (0, 0, 0, 0);
813   vertexList->vertex.set1Value (1, 1, 1, 1);
814   vertexList->vertex.set1Value (2, 5, 1, 1);
815 
816   // Line
817   int N_LINE = N;
818   int *lineindex = new int[N_LINE*3];
819   for (int i=0; i<N_LINE-1; i++) {
820     lineindex[i*3] = i;
821     lineindex[i*3+1] = i+1;
822     lineindex[i*3+2] = -1;
823   }
824   int i = N_LINE-1;
825   lineindex[i*3] = i;
826   lineindex[i*3+1] = 0;
827   lineindex[i*3+2] = -1;
828 
829   SoIndexedLineSet *vertIndex = new SoIndexedLineSet();
830   vertIndex->coordIndex.setValues (0, N_LINE*3, lineindex);
831   root->addChild(vertIndex);
832 
833   delete []lineindex;
834 }
835 
836 
837 void draw_filled_polygon_test (SoSeparator* root)
838 {
839   // Points in N*3 float array.
840   SoVertexProperty *vertexList = new SoVertexProperty();
841   root->addChild(vertexList);
842 
843   int N = 3;
844 #if 0
845   for (int i=0; i<N; i++)
846     vertexList->vertex.set1Value (i, 1.2*i, 1.3*i*i, 1.4*i);
847 #endif // 0
848   vertexList->vertex.set1Value (0, 0, 0, 0);
849   vertexList->vertex.set1Value (1, 1, 1, 1);
850   vertexList->vertex.set1Value (2, 5, 1, 1);
851 
852   // Face 1
853   int N_VERTICES = (N+1)*2;
854   int *faceindex = new int[N_VERTICES];
855   for (int i=0; i<N; i++)
856     faceindex[i] = i;
857   faceindex[N] = -1;
858 
859   // Face 2
860   for (int i=0; i<N; i++)
861     faceindex[N+1+i] = N-1-i;
862   faceindex[N*2+1] = -1;
863 
864   SoIndexedFaceSet *vertIndex = new SoIndexedFaceSet();
865   vertIndex->coordIndex.setValues (0, N_VERTICES, faceindex);
866   root->addChild(vertIndex);
867 
868   SoShapeHints * hints = new SoShapeHints;
869   hints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
870   hints->shapeType = SoShapeHints::SOLID;
871   root->addChild(hints);
872 
873   delete[] faceindex;
874 }
875 
876 void draw_indexed_line_test (SoSeparator* root)
877 {
878   // Put a wireframe cube in the scene.
879   SoSeparator *cubeSep = new SoSeparator();
880 
881   const SbVec3f CubeMin   = SbVec3f(-1.0, -1.0, -1.0);
882   const SbVec3f CubeMax   = SbVec3f( 1.0,  1.0,  1.0);
883 
884   ////////////////////////////////////////////////////////////
885 
886   //:
887   // \verbatim
888   //  Create an array of points at the vertices of the cube.
889   //
890   //                             y
891   //                             ^
892   //                  2          |                 3
893   //                 .-----------|----------------.
894   //                /            |               /|
895   //               / |           |              / |
896   //              /                            /  |
897   //           7 /   |                      6 /   |
898   //            .----------------------------.    |
899   //            |    |                       |    |
900   //            |                            |    |
901   //            |    |                       |  ------> x
902   //            |                            |    |
903   //            |    |                       |    |
904   //            |                            |    |
905   //            |    |                       |    |
906   //            |    .- - - - - - - - - - - -|- - .
907   //            |     0                      |   /  1
908   //            |  /                         |  /
909   //            |                            | /
910   //            |/                           |/
911   //            .----------------------------.
912   //          4                                5
913   // \endverbatim
914 
915   constexpr int numCubeVerts = 8;
916   static float cubeVerts[numCubeVerts][3] =
917   {
918     { CubeMin[0],  CubeMin[1],  CubeMax[2] },  // vert  0
919     { CubeMax[0],  CubeMin[1],  CubeMax[2] },  // vert  1
920     { CubeMin[0],  CubeMax[1],  CubeMax[2] },  // vert  2
921     { CubeMax[0],  CubeMax[1],  CubeMax[2] },  // vert  3
922 
923     { CubeMin[0],  CubeMin[1],  CubeMin[2] },  // vert  4
924     { CubeMax[0],  CubeMin[1],  CubeMin[2] },  // vert  5
925     { CubeMin[0],  CubeMax[1],  CubeMin[2] },  // vert  6
926     { CubeMax[0],  CubeMax[1],  CubeMin[2] }   // vert  7
927   };
928 
929   ////////////////////////////////////////////////////////////
930   //
931   //  Index into the array of vertices to create segments
932   //  defining the edges of the cube.
933   //
934   //  For example,  0, 1, -1  will designate a segment from
935   //  cubeVerts[0] to cubeVerts[1].
936 
937   SoVertexProperty *vertexList = new SoVertexProperty();
938   vertexList->vertex.setValues( 0,  numCubeVerts,  cubeVerts);
939   root->addChild(vertexList);
940 
941   constexpr int numEdgeIndexes = 36;
942   static int32_t cubeIndex[numEdgeIndexes] =
943   {
944     0, 1, -1,              // -1 terminates the edge.
945     2, 3, -1,
946     0, 2, -1,
947     1, 3, -1,
948 
949     4, 5, -1,
950     6, 7, -1,
951     4, 6, -1,
952     5, 7, -1,
953 
954     0, 4, -1,
955     1, 5, -1,
956     2, 6, -1,
957     3, 7, -1,
958   };
959 
960   SoIndexedLineSet *vertIndex = new SoIndexedLineSet();
961   vertIndex->coordIndex.setValues(0, numEdgeIndexes, cubeIndex);
962   root->addChild(vertIndex);
963   root->addChild(cubeSep);
964 }
965 
966 void draw_primitives_test (SoSeparator* root)
967 {
968   root->addChild (new SoCone);
969   root->addChild (new SoCylinder);
970   root->addChild (new SoSphere);
971 }
972 
973 #endif
974