@@ -225,14 +225,14 @@ void GlyphGeom::addComet(const Point& p1, const Point& p2, double radius, int re
225225 generateComet (p1, p2, radius, resolution, color1, color2, sphere_extrusion);
226226}
227227
228- void GlyphGeom::addBox (const Point& center, Tensor& t, double scale, ColorRGB& node_color)
228+ void GlyphGeom::addBox (const Point& center, Tensor& t, double scale, ColorRGB& node_color, bool normalize )
229229{
230- generateBox (center, t, scale, node_color);
230+ generateBox (center, t, scale, node_color, normalize );
231231}
232232
233- void GlyphGeom::addEllipsoid (const Point& p, Tensor& t, int resolution, const ColorRGB& color)
233+ void GlyphGeom::addEllipsoid (const Point& p, Tensor& t, double scale, int resolution, const ColorRGB& color, bool normalize )
234234{
235- generateEllipsoid (p, t, resolution, color, false );
235+ generateEllipsoid (p, t, scale, resolution, color, false , normalize );
236236}
237237
238238void GlyphGeom::addCylinder (const Point& p1, const Point& p2, double radius, int resolution,
@@ -708,30 +708,97 @@ void GlyphGeom::generateComet(const Point& p1, const Point& p2,
708708 }
709709}
710710
711- void GlyphGeom::generateBox ( const Point& center, Tensor& t, double scale, ColorRGB& node_color )
711+ void reorderTensor (std::vector<Vector>& eigvectors, Vector& eigvals )
712712{
713+ if (eigvals[0 ] < eigvals[1 ])
714+ {
715+ double temp = eigvals[0 ];
716+ eigvals[0 ] = eigvals[1 ];
717+ eigvals[1 ] = temp;
718+ Vector tempVec = eigvectors[0 ];
719+ eigvectors[0 ] = eigvectors[1 ];
720+ eigvectors[1 ] = tempVec;
721+ }
722+ if (eigvals[1 ] < eigvals[2 ])
723+ {
724+ double temp = eigvals[1 ];
725+ eigvals[1 ] = eigvals[2 ];
726+ eigvals[2 ] = temp;
727+ Vector tempVec = eigvectors[1 ];
728+ eigvectors[1 ] = eigvectors[2 ];
729+ eigvectors[2 ] = tempVec;
730+ }
731+ if (eigvals[0 ] < eigvals[1 ])
732+ {
733+ double temp = eigvals[0 ];
734+ eigvals[0 ] = eigvals[1 ];
735+ eigvals[1 ] = temp;
736+ Vector tempVec = eigvectors[0 ];
737+ eigvectors[0 ] = eigvectors[1 ];
738+ eigvectors[1 ] = tempVec;
739+ }
740+ }
741+
742+ void GlyphGeom::generateBox (const Point& center, Tensor& t, double scale, ColorRGB& node_color, bool normalize)
743+ {
744+ double zeroThreshold = 0.000001 ;
713745 double eigval1, eigval2, eigval3;
714746 t.get_eigenvalues (eigval1, eigval2, eigval3);
715747
716- Vector scaled_eigenvals (abs (eigval1), abs (eigval2), abs (eigval3));
717- scaled_eigenvals *= scale;
748+ Vector eigvals (abs (eigval1), abs (eigval2), abs (eigval3));
749+ if (normalize)
750+ eigvals.normalize ();
751+ eigvals *= scale;
752+
753+ std::vector<Vector> eigvectors (3 );
754+ t.get_eigenvectors (eigvectors[0 ], eigvectors[1 ], eigvectors[2 ]);
755+
756+ // Checks to see if eigenvalues are close to 0
757+ bool eig_x_0 = eigvals.x () <= zeroThreshold;
758+ bool eig_y_0 = eigvals.y () <= zeroThreshold;
759+ bool eig_z_0 = eigvals.z () <= zeroThreshold;
760+
761+ // Set to 0 if below threshold
762+ eigvals[0 ] = (!eig_x_0) * eigvals[0 ];
763+ eigvals[1 ] = (!eig_y_0) * eigvals[1 ];
764+ eigvals[2 ] = (!eig_z_0) * eigvals[2 ];
718765
719- Vector eigvec1, eigvec2, eigvec3;
720- t.get_eigenvectors (eigvec1, eigvec2, eigvec3);
766+ bool flatTensor = (eig_x_0 + eig_y_0 + eig_z_0) >= 1 ;
767+ if (flatTensor)
768+ {
769+ reorderTensor (eigvectors, eigvals);
770+
771+ eig_x_0 = eigvals.x () <= zeroThreshold;
772+ eig_y_0 = eigvals.y () <= zeroThreshold;
773+ eig_z_0 = eigvals.z () <= zeroThreshold;
774+ // Check for zero eigenvectors
775+ if (eig_x_0)
776+ {
777+ eigvectors[0 ] = Cross (eigvectors[1 ], eigvectors[2 ]);
778+ }
779+ else if (eig_y_0)
780+ {
781+ eigvectors[1 ] = Cross (eigvectors[0 ], eigvectors[2 ]);
782+ }
783+ else if (eig_z_0)
784+ {
785+ eigvectors[2 ] = Cross (eigvectors[0 ], eigvectors[1 ]);
786+ }
787+ }
721788
722- Transform rotate (Point (0.0 , 0.0 , 0.0 ), eigvec1, eigvec2, eigvec3 );
789+ Transform rotate (Point (0.0 , 0.0 , 0.0 ), eigvectors[ 0 ], eigvectors[ 1 ], eigvectors[ 2 ] );
723790 Transform trans = rotate;
724791 trans.pre_translate ((Vector) center);
725792
726793 // Rotate and translate points
727- Vector p1 = Vector (trans * Point (scaled_eigenvals * Vector (-1.0 , 1.0 , 1.0 )));
728- Vector p2 = Vector (trans * Point (scaled_eigenvals * Vector (-1.0 , 1.0 , -1.0 )));
729- Vector p3 = Vector (trans * Point (scaled_eigenvals * Vector (1.0 , 1.0 , 1.0 )));
730- Vector p4 = Vector (trans * Point (scaled_eigenvals * Vector (1.0 , 1.0 , -1.0 )));
731- Vector p5 = Vector (trans * Point (scaled_eigenvals * Vector (-1.0 , -1.0 , 1.0 )));
732- Vector p6 = Vector (trans * Point (scaled_eigenvals * Vector (-1.0 , -1.0 , -1.0 )));
733- Vector p7 = Vector (trans * Point (scaled_eigenvals * Vector (1.0 , -1.0 , 1.0 )));
734- Vector p8 = Vector (trans * Point (scaled_eigenvals * Vector (1.0 , -1.0 , -1.0 )));
794+ Vector p1 = Vector (trans * Point (eigvals * Vector (-1.0 , 1.0 , 1.0 )));
795+ Vector p2 = Vector (trans * Point (eigvals * Vector (-1.0 , 1.0 , -1.0 )));
796+ Vector p3 = Vector (trans * Point (eigvals * Vector (1.0 , 1.0 , 1.0 )));
797+ Vector p4 = Vector (trans * Point (eigvals * Vector (1.0 , 1.0 , -1.0 )));
798+ Vector p5 = Vector (trans * Point (eigvals * Vector (-1.0 , -1.0 , 1.0 )));
799+ Vector p6 = Vector (trans * Point (eigvals * Vector (-1.0 , -1.0 , -1.0 )));
800+ Vector p7 = Vector (trans * Point (eigvals * Vector (1.0 , -1.0 , 1.0 )));
801+ Vector p8 = Vector (trans * Point (eigvals * Vector (1.0 , -1.0 , -1.0 )));
735802
736803 // Rotate norms
737804 Vector x_vec = rotate * Vector (1 , 0 , 0 );
@@ -770,128 +837,147 @@ void GlyphGeom::generateBoxSide(const Vector& p1, const Vector& p2, const Vector
770837 indices_.push_back (offset);
771838}
772839
773- void GlyphGeom::generateEllipsoid (const Point& center, Tensor& t, int resolution, const ColorRGB& color, bool half)
840+ void GlyphGeom::generateEllipsoid (const Point& center, Tensor& t, double scale, int resolution, const ColorRGB& color, bool half, bool normalize )
774841{
775- Vector eigvec1, eigvec2, eigvec3;
776- t.get_eigenvectors (eigvec1, eigvec2, eigvec3);
842+ double zeroThreshold = 0.000001 ;
843+ std::vector<Vector> eigvectors (3 );
844+ t.get_eigenvectors (eigvectors[0 ], eigvectors[1 ], eigvectors[2 ]);
777845
778- double eigval1, eigval2, eigval3;
779- t.get_eigenvalues (eigval1, eigval2, eigval3);
780- Vector scaled_eigenvals = Vector (eigval1, eigval2, eigval3);
846+ double eigval1, eigval2, eigval3;
847+ t.get_eigenvalues (eigval1, eigval2, eigval3);
848+ Vector eigvals = Vector (fabs (eigval1), fabs (eigval2), fabs (eigval3));
849+ if (normalize)
850+ eigvals.normalize ();
851+ eigvals *= scale;
781852
853+ // Checks to see if eigenvalues are close to 0
854+ bool eig_x_0 = eigvals.x () <= zeroThreshold;
855+ bool eig_y_0 = eigvals.y () <= zeroThreshold;
856+ bool eig_z_0 = eigvals.z () <= zeroThreshold;
857+
858+ // Set to 0 if below threshold
859+ eigvals[0 ] = (!eig_x_0) * eigvals[0 ];
860+ eigvals[1 ] = (!eig_y_0) * eigvals[1 ];
861+ eigvals[2 ] = (!eig_z_0) * eigvals[2 ];
862+
863+ bool flatTensor = (eig_x_0 + eig_y_0 + eig_z_0) >= 1 ;
864+ Vector zero_norm;
865+
866+ if (flatTensor)
867+ {
868+ reorderTensor (eigvectors, eigvals);
869+
870+ eig_x_0 = eigvals.x () <= zeroThreshold;
871+ eig_y_0 = eigvals.y () <= zeroThreshold;
872+ eig_z_0 = eigvals.z () <= zeroThreshold;
782873 // Check for zero eigenvectors
783- bool zero_norm_used = false ;
784- Vector zero_norm;
785- double epsilon = pow (2 , -52 );
786- if (scaled_eigenvals[0 ] <= epsilon)
874+ if (eig_x_0)
787875 {
788- zero_norm_used = true ;
789- zero_norm = Cross (eigvec2, eigvec3);
790- eigvec1 = Cross (eigvec2, eigvec3);
876+ zero_norm = Cross (eigvectors[1 ], eigvectors[2 ]);
877+ eigvectors[0 ] = zero_norm;
791878 }
792- else if (scaled_eigenvals[ 1 ] <= epsilon )
879+ else if (eig_y_0 )
793880 {
794- zero_norm_used = true ;
795- zero_norm = Cross (eigvec1, eigvec3);
796- eigvec2 = Cross (eigvec1, eigvec3);
881+ zero_norm = Cross (eigvectors[0 ], eigvectors[2 ]);
882+ eigvectors[1 ] = zero_norm;
797883 }
798- else if (scaled_eigenvals[ 2 ] <= epsilon )
884+ else if (eig_z_0 )
799885 {
800- zero_norm_used = true ;
801- zero_norm = Cross (eigvec1, eigvec2);
802- eigvec3 = Cross (eigvec1, eigvec2);
886+ zero_norm = Cross (eigvectors[0 ], eigvectors[1 ]);
887+ eigvectors[2 ] = zero_norm;
803888 }
889+ }
890+
891+ Transform rotate (Point (0.0 , 0.0 , 0.0 ), eigvectors[0 ], eigvectors[1 ], eigvectors[2 ]);
892+ Transform trans = rotate;
893+ trans.pre_translate ((Vector) center);
894+
895+ trans.post_scale (Vector (1.0 ,1.0 ,1.0 ) * eigvals);
896+ rotate.post_scale (Vector (1.0 ,1.0 ,1.0 ) / eigvals);
897+
898+ int nu = resolution + 1 ;
804899
805- Transform rotate (Point (0.0 , 0.0 , 0.0 ), eigvec1, eigvec2, eigvec3);
806- Transform trans = rotate;
807- trans.pre_translate ((Vector) center);
900+ // Half ellipsoid criteria.
901+ int nv = resolution;
902+ if (half) nv /= 2 ;
903+
904+ // Should only happen when doing half ellipsoids.
905+ if (nv < 2 ) nv = 2 ;
906+
907+ double end = half ? M_PI / 2 : M_PI;
908+
909+ SinCosTable tab1 (nu, 0 , 2 * M_PI);
910+ SinCosTable tab2 (nv, 0 , end);
911+
912+ // Draw the ellipsoid
913+ for (int v = 0 ; v<nv - 1 ; v++)
914+ {
915+ double nr1 = tab2.sin (v + 1 );
916+ double nr2 = tab2.sin (v);
808917
809- trans. post_scale ( Vector ( 1.0 , 1.0 , 1.0 ) * scaled_eigenvals );
810- rotate. post_scale ( Vector ( 1.0 , 1.0 , 1.0 ) / scaled_eigenvals );
918+ double nz1 = tab2. cos (v + 1 );
919+ double nz2 = tab2. cos (v );
811920
812- int nu = resolution + 1 ;
921+ for (int u = 0 ; u<nu; u++)
922+ {
923+ uint32_t offset = static_cast <uint32_t >(numVBOElements_);
924+ double nx = tab1.sin (u);
925+ double ny = tab1.cos (u);
813926
814- // Half ellipsoid criteria.
815- int nv = resolution ;
816- if (half) nv /= 2 ;
927+ double x1 = nr1 * nx;
928+ double y1 = nr1 * ny ;
929+ double z1 = nz1 ;
817930
818- // Should only happen when doing half ellipsoids.
819- if (nv < 2 ) nv = 2 ;
931+ double x2 = nr2 * nx;
932+ double y2 = nr2 * ny;
933+ double z2 = nz2;
820934
821- double end = half ? M_PI / 2 : M_PI;
935+ // Rotate and translate points
936+ Vector p1 = Vector (trans * Point (x1, y1, z1));
937+ Vector p2 = Vector (trans * Point (x2, y2, z2));
822938
823- SinCosTable tab1 (nu, 0 , 2 * M_PI);
824- SinCosTable tab2 (nv, 0 , end);
939+ Vector v1, v2;
825940
826- // Draw the ellipsoid
827- for (int v = 0 ; v<nv - 1 ; v++)
941+ if (flatTensor)
942+ {
943+ // Avoids recalculating norm vector and prevents vectors with infinite length
944+ bool first_half = v < nv/2 ;
945+ v1 = first_half ? zero_norm : -zero_norm;
946+ v2 = first_half ? zero_norm : -zero_norm;
947+ }
948+ else
828949 {
829- double nr1 = tab2.sin (v + 1 );
830- double nr2 = tab2.sin (v);
831-
832- double nz1 = tab2.cos (v + 1 );
833- double nz2 = tab2.cos (v);
834-
835- for (int u = 0 ; u<nu; u++)
836- {
837- uint32_t offset = static_cast <uint32_t >(numVBOElements_);
838- double nx = tab1.sin (u);
839- double ny = tab1.cos (u);
840-
841- double x1 = nr1 * nx;
842- double y1 = nr1 * ny;
843- double z1 = nz1;
844-
845- double x2 = nr2 * nx;
846- double y2 = nr2 * ny;
847- double z2 = nz2;
848-
849- // Rotate and translate points
850- Vector p1 = Vector (trans * Point (x1, y1, z1));
851- Vector p2 = Vector (trans * Point (x2, y2, z2));
852-
853- Vector v1, v2;
854-
855- if (zero_norm_used)
856- {
857- // Avoids recalculating norm vector and prevents vectors with infinite length
858- bool first_half = v < nv/2 ;
859- v1 = first_half ? zero_norm : -zero_norm;
860- v2 = first_half ? zero_norm : -zero_norm;
861- }
862- else
863- {
864- // Rotate norms
865- v1 = rotate * Vector (x1, y1, z1);
866- v2 = rotate * Vector (x2, y2, z2);
867- }
868-
869- v1.safe_normalize ();
870- v2.safe_normalize ();
871-
872- // Transorm points and add to points list
873- points_.push_back (p1);
874- points_.push_back (p2);
875-
876- // Add normals
877- normals_.push_back (v1);
878- normals_.push_back (v2);
879-
880- // Add color vectors from parameters
881- colors_.push_back (color);
882- colors_.push_back (color);
883-
884- numVBOElements_ += 2 ;
885-
886- indices_.push_back (0 + offset);
887- indices_.push_back (1 + offset);
888- indices_.push_back (2 + offset);
889- indices_.push_back (2 + offset);
890- indices_.push_back (1 + offset);
891- indices_.push_back (3 + offset);
892- }
893- for (int jj = 0 ; jj < 6 ; jj++) indices_.pop_back ();
950+ // Rotate norms
951+ v1 = rotate * Vector (x1, y1, z1);
952+ v2 = rotate * Vector (x2, y2, z2);
894953 }
954+
955+ v1.safe_normalize ();
956+ v2.safe_normalize ();
957+
958+ // Transorm points and add to points list
959+ points_.push_back (p1);
960+ points_.push_back (p2);
961+
962+ // Add normals
963+ normals_.push_back (v1);
964+ normals_.push_back (v2);
965+
966+ // Add color vectors from parameters
967+ colors_.push_back (color);
968+ colors_.push_back (color);
969+
970+ numVBOElements_ += 2 ;
971+
972+ indices_.push_back (0 + offset);
973+ indices_.push_back (1 + offset);
974+ indices_.push_back (2 + offset);
975+ indices_.push_back (2 + offset);
976+ indices_.push_back (1 + offset);
977+ indices_.push_back (3 + offset);
978+ }
979+ for (int jj = 0 ; jj < 6 ; jj++) indices_.pop_back ();
980+ }
895981}
896982
897983void GlyphGeom::generateLine (const Point& p1, const Point& p2, const ColorRGB& color1, const ColorRGB& color2)
0 commit comments