11#! /usr/bin/env python
22# -*- coding: utf-8 -*-
3- import os , sys , re
3+ import os
4+ import sys
5+ import re
46
57from solid import *
68from solid .utils import *
79
810from euclid import *
911
10- ONE_THIRD = 1 / 3.0
12+ ONE_THIRD = 1 / 3.0
13+
1114
1215def affine_combination (a , b , weight = 0.5 ):
1316 '''
1417 Note that weight is a fraction of the distance between self and other.
1518 So... 0.33 is a point .33 of the way between self and other.
1619 '''
1720 if hasattr (a , 'z' ):
18- return Point3 ( ( 1 - weight )* a .x + weight * b .x ,
19- ( 1 - weight )* a .y + weight * b .y ,
20- ( 1 - weight )* a .z + weight * b .z ,
21- )
21+ return Point3 (( 1 - weight ) * a .x + weight * b .x ,
22+ ( 1 - weight ) * a .y + weight * b .y ,
23+ ( 1 - weight ) * a .z + weight * b .z ,
24+ )
2225 else :
23- return Point2 ( (1 - weight )* a .x + weight * b .x ,
24- (1 - weight )* a .y + weight * b .y ,
25- )
26-
27- def kochify_3d (a , b , c ,
28- ab_weight = 0.5 , bc_weight = 0.5 , ca_weight = 0.5 ,
29- pyr_a_weight = ONE_THIRD , pyr_b_weight = ONE_THIRD , pyr_c_weight = ONE_THIRD ,
30- pyr_height_weight = ONE_THIRD
31- ):
26+ return Point2 ((1 - weight ) * a .x + weight * b .x ,
27+ (1 - weight ) * a .y + weight * b .y ,
28+ )
29+
30+
31+ def kochify_3d (a , b , c ,
32+ ab_weight = 0.5 , bc_weight = 0.5 , ca_weight = 0.5 ,
33+ pyr_a_weight = ONE_THIRD , pyr_b_weight = ONE_THIRD , pyr_c_weight = ONE_THIRD ,
34+ pyr_height_weight = ONE_THIRD
35+ ):
3236 '''
3337 Point3s a, b, and c must be coplanar and define a face
3438 ab_weight, etc define the subdivision of the original face
@@ -39,52 +43,52 @@ def kochify_3d(a, b, c,
3943 new_a = affine_combination (a , b , ab_weight )
4044 new_b = affine_combination (b , c , bc_weight )
4145 new_c = affine_combination (c , a , ca_weight )
42-
43- triangles .extend ( [[a , new_a , new_c ], [b , new_b , new_a ], [c , new_c , new_b ]])
44-
45- avg_pt_x = a .x * pyr_a_weight + b .x * pyr_b_weight + c .x * pyr_c_weight
46- avg_pt_y = a .y * pyr_a_weight + b .y * pyr_b_weight + c .y * pyr_c_weight
47- avg_pt_z = a .z * pyr_a_weight + b .z * pyr_b_weight + c .z * pyr_c_weight
48-
46+
47+ triangles .extend ([[a , new_a , new_c ], [b , new_b , new_a ], [c , new_c , new_b ]])
48+
49+ avg_pt_x = a .x * pyr_a_weight + b .x * pyr_b_weight + c .x * pyr_c_weight
50+ avg_pt_y = a .y * pyr_a_weight + b .y * pyr_b_weight + c .y * pyr_c_weight
51+ avg_pt_z = a .z * pyr_a_weight + b .z * pyr_b_weight + c .z * pyr_c_weight
52+
4953 center_pt = Point3 (avg_pt_x , avg_pt_y , avg_pt_z )
50-
51- # The top of the pyramid will be on a normal
54+
55+ # The top of the pyramid will be on a normal
5256 ab_vec = b - a
5357 bc_vec = c - b
5458 ca_vec = a - c
5559 normal = ab_vec .cross (bc_vec ).normalized ()
56- avg_side_length = (abs (ab_vec ) + abs (bc_vec ) + abs (ca_vec ))/ 3
60+ avg_side_length = (abs (ab_vec ) + abs (bc_vec ) + abs (ca_vec )) / 3
5761 pyr_h = avg_side_length * pyr_height_weight
5862 pyr_pt = LineSegment3 (center_pt , normal , pyr_h ).p2
59-
60-
63+
6164 triangles .extend ([[new_a , pyr_pt , new_c ], [new_b , pyr_pt , new_a ], [new_c , pyr_pt , new_b ]])
62-
65+
6366 return triangles
64-
6567
66- def kochify (seg , height_ratio = 0.33 , left_loc = 0.33 , midpoint_loc = 0.5 , right_loc = 0.66 ):
68+
69+ def kochify (seg , height_ratio = 0.33 , left_loc = 0.33 , midpoint_loc = 0.5 , right_loc = 0.66 ):
6770 a , b = seg .p1 , seg .p2
6871 l = affine_combination (a , b , left_loc )
6972 c = affine_combination (a , b , midpoint_loc )
7073 r = affine_combination (a , b , right_loc )
71- # The point of the new triangle will be height_ratio * abs(seg) long,
74+ # The point of the new triangle will be height_ratio * abs(seg) long,
7275 # and run perpendicular to seg, through c.
7376 perp = seg .v .cross ().normalized ()
74-
75- c_height = height_ratio * abs (seg )
77+
78+ c_height = height_ratio * abs (seg )
7679 perp_pt = LineSegment2 (c , perp , - c_height ).p2
77-
80+
7881 # For the moment, assume perp_pt is on the right side of seg.
7982 # Will confirm this later if needed
80- return [ LineSegment2 (a , l ),
81- LineSegment2 (l , perp_pt ),
82- LineSegment2 (perp_pt , r ),
83- LineSegment2 (r , b )]
83+ return [LineSegment2 (a , l ),
84+ LineSegment2 (l , perp_pt ),
85+ LineSegment2 (perp_pt , r ),
86+ LineSegment2 (r , b )]
87+
8488
8589def main_3d (out_dir ):
8690 gens = 4
87-
91+
8892 # Parameters
8993 ab_weight = 0.5
9094 bc_weight = 0.5
@@ -94,113 +98,112 @@ def main_3d(out_dir):
9498 pyr_c_weight = ONE_THIRD
9599 pyr_height_weight = ONE_THIRD
96100 pyr_height_weight = ONE_THIRD
97- # pyr_height_weight = .25
98-
101+ # pyr_height_weight = .25
102+
99103 all_polys = union ()
100-
104+
101105 # setup
102106 ax , ay , az = 100 , - 100 , 100
103- bx , by , bz = 100 , 100 ,- 100
107+ bx , by , bz = 100 , 100 , - 100
104108 cx , cy , cz = - 100 , 100 , 100
105109 dx , dy , dz = - 100 , - 100 , - 100
106- generations = [ [[ Point3 (ax , ay , az ), Point3 (bx , by , bz ), Point3 (cx , cy , cz )],
107- [ Point3 (bx , by , bz ), Point3 (ax , ay , az ), Point3 (dx , dy , dz )],
108- [ Point3 (ax , ay , az ), Point3 (cx , cy , cz ), Point3 (dx , dy , dz )],
109- [ Point3 (cx , cy , cz ), Point3 (bx , by , bz ), Point3 (dx , dy , dz )],
110- ]
110+ generations = [[[Point3 (ax , ay , az ), Point3 (bx , by , bz ), Point3 (cx , cy , cz )],
111+ [Point3 (bx , by , bz ), Point3 (ax , ay , az ), Point3 (dx , dy , dz )],
112+ [Point3 (ax , ay , az ), Point3 (cx , cy , cz ), Point3 (dx , dy , dz )],
113+ [Point3 (cx , cy , cz ), Point3 (bx , by , bz ), Point3 (dx , dy , dz )],
111114 ]
112-
115+ ]
116+
113117 # Recursively generate snowflake segments
114118 for g in range (1 , gens ):
115- generations .append ([])
116- for a , b , c in generations [g - 1 ]:
117- new_tris = kochify_3d (a , b , c ,
118- ab_weight , bc_weight , ca_weight ,
119- pyr_a_weight , pyr_b_weight ,pyr_c_weight ,
120- pyr_height_weight )
119+ generations .append ([])
120+ for a , b , c in generations [g - 1 ]:
121+ new_tris = kochify_3d (a , b , c ,
122+ ab_weight , bc_weight , ca_weight ,
123+ pyr_a_weight , pyr_b_weight , pyr_c_weight ,
124+ pyr_height_weight )
121125 # new_tris = kochify_3d( a, b, c)
122126 generations [g ].extend (new_tris )
123-
127+
124128 # Put all generations into SCAD
125129 orig_length = abs (generations [0 ][0 ][1 ] - generations [0 ][0 ][0 ])
126130 for g , a_gen in enumerate (generations ):
127131 # Move each generation up in y so it doesn't overlap the others
128- h = orig_length * 1.5 * g
129-
132+ h = orig_length * 1.5 * g
133+
130134 # Build the points and triangles arrays that SCAD needs
131135 faces = []
132136 points = []
133- for a ,b , c in a_gen :
134- points .extend ([ [a .x , a .y , a .z ], [b .x , b .y , b .z ], [c .x , c .y , c .z ]])
137+ for a , b , c in a_gen :
138+ points .extend ([[a .x , a .y , a .z ], [b .x , b .y , b .z ], [c .x , c .y , c .z ]])
135139 t = len (points )
136- faces .append ([t - 3 , t - 2 , t - 1 ])
137-
140+ faces .append ([t - 3 , t - 2 , t - 1 ])
141+
138142 # Do the SCAD
139143 edges = [list (range (len (points )))]
140144 all_polys .add (up (h )(
141- polyhedron (points = points , faces = faces )
142- )
145+ polyhedron (points = points , faces = faces )
146+ )
143147 )
144-
148+
145149 file_out = os .path .join (out_dir , 'koch_3d.scad' )
146150 cur_file = __file__
147- print ("%(cur_file)s: SCAD file written to: %(file_out)s" % vars ())
148- scad_render_to_file (all_polys , file_out , include_orig_code = True )
151+ print ("%(cur_file)s: SCAD file written to: %(file_out)s" % vars ())
152+ scad_render_to_file (all_polys , file_out , include_orig_code = True )
153+
149154
150155def main (out_dir ):
151156 # Parameters
152157 midpoint_weight = 0.5
153158 height_ratio = 0.25
154159 left_loc = ONE_THIRD
155160 midpoint_loc = 0.5
156- right_loc = 2 * ONE_THIRD
161+ right_loc = 2 * ONE_THIRD
157162 gens = 5
158-
159- # Results
163+
164+ # Results
160165 all_polys = union ()
161-
166+
162167 # setup
163168 ax , ay = 0 , 0
164169 bx , by = 100 , 0
165170 cx , cy = 50 , 86.6
166- base_seg1 = LineSegment2 ( Point2 (ax , ay ), Point2 (cx , cy ))
167- base_seg2 = LineSegment2 ( Point2 (cx , cy ), Point2 (bx , by ))
168- base_seg3 = LineSegment2 ( Point2 (bx , by ), Point2 (ax , ay ))
171+ base_seg1 = LineSegment2 (Point2 (ax , ay ), Point2 (cx , cy ))
172+ base_seg2 = LineSegment2 (Point2 (cx , cy ), Point2 (bx , by ))
173+ base_seg3 = LineSegment2 (Point2 (bx , by ), Point2 (ax , ay ))
169174 generations = [[base_seg1 , base_seg2 , base_seg3 ]]
170-
171-
175+
172176 # Recursively generate snowflake segments
173177 for g in range (1 , gens ):
174- generations .append ([])
175- for seg in generations [g - 1 ]:
178+ generations .append ([])
179+ for seg in generations [g - 1 ]:
176180 generations [g ].extend (kochify (seg , height_ratio , left_loc , midpoint_loc , right_loc ))
177181 # generations[g].extend(kochify(seg))
178-
182+
179183 # # Put all generations into SCAD
180184 orig_length = abs (generations [0 ][0 ])
181185 for g , a_gen in enumerate (generations ):
182- points = [s .p1 for s in a_gen ]
186+ points = [s .p1 for s in a_gen ]
183187 # points.append(a_gen[-1].p2) # add the last point
184-
188+
185189 rect_offset = 10
186-
190+
187191 # Just use arrays for points so SCAD understands
188192 points = [[p .x , p .y ] for p in points ]
189-
193+
190194 # Move each generation up in y so it doesn't overlap the others
191- h = orig_length * 1.5 * g
192-
195+ h = orig_length * 1.5 * g
196+
193197 # Do the SCAD
194198 edges = [list (range (len (points )))]
195- all_polys .add (forward (h )(polygon (points = points , paths = edges )))
196-
197- file_out = os .path .join (out_dir ,'koch.scad' )
198- cur_file = __file__
199- print ("%(cur_file)s: SCAD file written to: %(file_out)s " % vars ())
200- scad_render_to_file (all_polys , file_out , include_orig_code = True )
199+ all_polys .add (forward (h )(polygon (points = points , paths = edges )))
200+
201+ file_out = os .path .join (out_dir , 'koch.scad' )
202+ cur_file = __file__
203+ print ("%(cur_file)s: SCAD file written to: %(file_out)s " % vars ())
204+ scad_render_to_file (all_polys , file_out , include_orig_code = True )
201205
202206if __name__ == '__main__' :
203207 out_dir = sys .argv [1 ] if len (sys .argv ) > 1 else os .curdir
204208 main_3d (out_dir )
205209 main (out_dir )
206-
0 commit comments