33 This module contains the utility functions to vizualize differences
44"""
55
6- import numpy as np
7- import open3d as o3d
8- from diffCheck import diffcheck_bindings
96import Rhino .Geometry as rg
10- import System .Drawing
7+ from System .Drawing import Color
8+
119
1210class DFVizSettings :
1311 """
1412 This class compiles the settings for the vizualization into one object
1513 """
1614
17- def __init__ (self , source_valueType , target_valueType , upper_threshold , lower_threshold , palette ):
15+ def __init__ (self , source_valueType , target_valueType , upper_threshold ,
16+ lower_threshold , palette ):
1817
1918 self .source_valueType = source_valueType
2019 self .target_valueType = target_valueType
@@ -30,20 +29,19 @@ def interpolate_color(color1, color2, t):
3029 r = int (color1 .R + (color2 .R - color1 .R ) * t )
3130 g = int (color1 .G + (color2 .G - color1 .G ) * t )
3231 b = int (color1 .B + (color2 .B - color1 .B ) * t )
33- return System . Drawing . Color .FromArgb (r , g , b )
32+ return Color .FromArgb (r , g , b )
3433
3534
3635def value_to_color (value , min_value , max_value ):
3736 """Map a value to a color based on a spectral colormap."""
3837
3938 # Define the spectral colormap (simplified)
4039 colormap = [
41- System .Drawing .Color .FromArgb (0 , 0 , 255 ), # Blue
42- System .Drawing .Color .FromArgb (0 , 255 , 255 ), # Cyan
43- System .Drawing .Color .FromArgb (0 , 255 , 0 ), # Green
44- System .Drawing .Color .FromArgb (255 , 255 , 0 ), # Yellow
45- System .Drawing .Color .FromArgb (255 , 0 , 0 ), # Red
46- System .Drawing .Color .FromArgb (255 , 0 , 255 ) # Magenta
40+ Color .FromArgb (0 , 0 , 255 ), # Blue
41+ Color .FromArgb (0 , 255 , 255 ), # Cyan
42+ Color .FromArgb (0 , 255 , 0 ), # Green
43+ Color .FromArgb (255 , 255 , 0 ), # Yellow
44+ Color .FromArgb (255 , 0 , 0 ), # Red
4745 ]
4846
4947 # Normalize the value within the range
@@ -53,7 +51,7 @@ def value_to_color(value, min_value, max_value):
5351 t = (value - min_value ) / (max_value - min_value )
5452
5553 # Determine the segment in the colormap
56- n = len (colormap ) - 1
54+ n = len (colormap )- 1
5755 idx = int (t * n )
5856 if idx >= n :
5957 idx = n - 1
@@ -74,10 +72,11 @@ def color_pcd(pcd, values, min_value, max_values):
7472 return pcd
7573
7674
77- def create_legend (min_value , max_value , steps = 10 , base_point = rg .Point3d (0 , 0 , 0 ), width = 0.5 , height = 1 , spacing = 0 ):
75+ def create_legend (min_value , max_value , steps = 10 , base_point = rg .Point3d (0 , 0 , 0 ),
76+ width = 0.5 , height = 1 , spacing = 0 ):
7877 """
7978 Create a legend in Rhino with colored hatches and text labels.
80-
79+
8180 Parameters:
8281 min_value (float): Minimum value for the legend.
8382 max_value (float): Maximum value for the legend.
@@ -88,38 +87,93 @@ def create_legend(min_value, max_value, steps=10, base_point=rg.Point3d(0, 0, 0)
8887 spacing (float): Spacing between rectangles.
8988 """
9089 x , y , z = base_point .X , base_point .Y , base_point .Z
91-
90+
9291 legend_geometry = []
9392
94- for i in range (steps + 1 ):
93+ for i in range (steps + 1 ):
94+
9595 value = min_value + (max_value - min_value ) * i / steps
9696 color = value_to_color (value , min_value , max_value )
97-
97+
98+ if i > 0 :
99+ mesh = rg .Mesh ()
100+ for pt in rect_pts :
101+ mesh .Vertices .Add (pt )
102+ # color mesh
103+ mesh .Faces .AddFace (0 , 1 , 2 , 3 )
104+
105+ mesh .VertexColors .Add (previous_color .R , previous_color .G , previous_color .B )
106+ mesh .VertexColors .Add (previous_color .R , previous_color .G , previous_color .B )
107+ mesh .VertexColors .Add (color .R , color .G , color .B )
108+ mesh .VertexColors .Add (color .R , color .G , color .B )
109+ mesh .VertexColors .Add (color .R , color .G , color .B )
110+
111+
112+ polyline = rg .Polyline (rect_pts )
113+
114+ legend_geometry .append (mesh )
115+ # legend_geometry.append(polyline.ToPolylineCurve())
116+
117+ text_pt = rg .Point3d (x + 1.25 * width + spacing , y + i * (height + spacing ) + height / 10 , z )
118+ text_entity = rg .TextEntity ()
119+ text_entity .Plane = rg .Plane (text_pt , rg .Vector3d .ZAxis )
120+ text_entity .Text = f"{ value :.2f} "
121+ text_entity .TextHeight = height / 5
122+ legend_geometry .append (text_entity )
123+
98124 rect_pts = [
99125 rg .Point3d (x , y + i * (height + spacing ), z ),
100126 rg .Point3d (x + width , y + i * (height + spacing ), z ),
101127 rg .Point3d (x + width , y + (i + 1 ) * height + i * spacing , z ),
102128 rg .Point3d (x , y + (i + 1 ) * height + i * spacing , z ),
103- rg .Point3d (x , y + i * (height + spacing ), z )
104129 ]
105-
106- mesh = rg .Mesh ()
107- for pt in rect_pts :
108- mesh .Vertices .Add (pt )
109- mesh .Faces .AddFace (0 , 1 , 2 , 3 )
110- mesh .VertexColors .CreateMonotoneMesh (color )
111130
112- polyline = rg .Polyline (rect_pts )
113-
114- legend_geometry .append (mesh )
115-
116- legend_geometry .append (polyline .ToPolylineCurve ())
131+ previous_color = color
132+
133+ return legend_geometry
134+
135+
136+ def create_histogram (values , min_value , max_value , steps = 10 , base_point = rg .Point3d (0 ,0 ,0 ), height = 0.1 , spacing = 0.1 ):
137+ """
138+ Create a histogram in Rhino with a polyline representing value frequencies.
139+
140+ Parameters:
141+ values (list of float): List of values to calculate the histogram.
142+ min_value (float): Minimum value for the histogram.
143+ max_value (float): Maximum value for the histogram.
144+ steps (int): Number of steps in the histogram.
145+ base_point (rg.Point3d): The base point where the histogram starts.
146+ height (float): Height of each bin in the histogram.
147+ spacing (float): Spacing between bins.
148+ """
149+ histogram_geometry = []
150+
151+ # Calculate the size of each bin
152+ bin_size = (max_value - min_value ) / steps
153+
154+ # Initialize the frequency counts for each bin
155+ frequencies = [0 ] * (steps + 1 )
156+
157+ # Count the frequencies of values in each bin
158+ for value in values :
159+ if min_value <= value and value <= max_value :
160+ bin_index = (value - min_value ) // bin_size
161+ bin_index = int (bin_index )
162+ if bin_index == steps :
163+ bin_index -= 1
164+ frequencies [bin_index ] += 1
165+
166+ x , y , z = base_point .X , base_point .Y , base_point .Z
167+
168+ # Create points for the polyline representing the histogram
169+ points = [rg .Point3d (x , y , z )]
170+ for i in range (int (steps )):
117171
118- text_pt = rg . Point3d ( x + width + spacing , y + i * ( height + spacing ) + height / 2 , z )
119- text_entity = rg .TextEntity ( )
120- text_entity . Plane = rg .Plane ( text_pt , rg . Vector3d . ZAxis )
121- text_entity . Text = f" { value :.2f } "
122- text_entity . TextHeight = height / 2
123- legend_geometry .append (text_entity )
124-
125- return legend_geometry
172+ bar_height = frequencies [ i ] * height
173+ points . append ( rg .Point3d ( x + bar_height , y + i * ( spacing + height ), z ) )
174+ points . append ( rg .Point3d ( x , y + ( i + 1 ) * ( spacing + height ), z ) )
175+ # Create the polyline and add it to the histogram geometry
176+ polyline = rg . Polyline ( points )
177+ histogram_geometry .append (points )
178+
179+ return histogram_geometry
0 commit comments