def transf_t(t, r, s): plane = rh.CurvePerpFrame(path, rh.CurveParameter(path, t)) xform = rh.XformChangeBasis(plane, geo.Plane.WorldXY) xform = rh.XformMultiply(xform, rh.XformScale(s)) xform = rh.XformMultiply( xform, geo.Transform.Rotation(r, geo.Vector3d(0, 0, 1), rawu0)) return rh.TransformObject(profile, xform, True)
def rotateAroundVector(v,theta): sinThX = v.Y/math.sqrt(v.Y**2 + v.Z**2) cosThX = v.Z/math.sqrt(v.Y**2 + v.Z**2) sinThY = v.X cosThY = math.sqrt(v.Y**2 + v.Z**2) rotation = RhinoScript.XformMultiply(rotateYZ(sinThX,cosThX), rotateXZ(-sinThY,cosThY)) rotation = RhinoScript.XformMultiply(rotation, rotateXY(math.sin(theta),math.cos(theta))) rotation = RhinoScript.XformMultiply(rotation, rotateXZ(sinThY,cosThY)) rotation = RhinoScript.XformMultiply(rotation, rotateYZ(-sinThX,cosThX)) return rotation
def applyXform(target, source): targetXform = rs.BlockInstanceXform(target) sourceXform = rs.BlockInstanceXform(source) if targetXform is not None: plane = rs.PlaneTransform(rs.WorldXYPlane(), targetXform) # xformscale = rs.XformScale((1.0,20.0,1.0)) cob = rs.XformChangeBasis(rs.WorldXYPlane(), plane) cob_inverse = rs.XformChangeBasis(plane, rs.WorldXYPlane()) temp = rs.XformMultiply(sourceXform, cob) xform = rs.XformMultiply(cob_inverse, temp) rs.TransformObjects(target, xform)
def bbsolid(obj): if rs.IsBlockInstance(obj): arrMatrix = rs.BlockInstanceXform(obj) if arrMatrix is not None: # pointId = rs.AddPoint([0,0,0]) plane = rs.PlaneTransform(rs.WorldXYPlane(), arrMatrix) box = rs.BoundingBox(obj, plane) bb = rs.AddBox(box) # if box: # for i, point in enumerate(box): # rs.AddTextDot( i, point ) xformscale = rs.XformScale((1.0, 20.0, 1.0)) cob = rs.XformChangeBasis(rs.WorldXYPlane(), plane) cob_inverse = rs.XformChangeBasis(plane, rs.WorldXYPlane()) temp = rs.XformMultiply(xformscale, cob) xform = rs.XformMultiply(cob_inverse, temp) rs.TransformObjects(bb, xform) return bb
def Transform(dir,ninety,pt): v1 = [dir[0],dir[1],dir[2]] v2 = [ninety[0],ninety[1],ninety[2]] v3 = [pt[0],pt[1],pt[2]] xfrm1 = rs.XformRotation4([-1,0,0],[0,-1,0],[0,0,1], v1, v2, [0,0,1]) xfrm2 = rs.XformTranslation(v3) xfrm = rs.XformMultiply(xfrm2,xfrm1) return xfrm
def reorient_objects(objects, basePlane, targetPlane, copy=True): """performs a plane to plane reorient on an object w/ or w/out copying""" if targetPlane == None: return None else: world = rs.WorldXYPlane() xform1 = rs.XformChangeBasis(world, basePlane) xform2 = rs.XformChangeBasis(targetPlane, world) xform_final = rs.XformMultiply(xform2, xform1) transform = rs.TransformObjects(objects, xform_final, copy) return transform
def vrep_pose_from_plane(plane): """Creates a vrep-compatible transformation matrix from a Rhino/Grasshopper plane. This function might need rework as the source of the 90-deg Y rotation need is not entirely clear to me (related to the RFL model mismatch). """ translation_matrix = rs.XformTranslation(((plane[0][0]), (plane[0][1]), plane[0][2])) plane_start = rs.PlaneFromFrame(rs.AddPoint(0, 0, 0), rs.AddPoint(1, 0, 0), rs.AddPoint(0, 1, 0)) plane_end = rs.PlaneFromFrame(rs.AddPoint(0, 0, 0), rs.AddPoint(plane[1][0], (plane[1][1]), plane[1][2]), rs.AddPoint(plane[2][0], plane[2][1], plane[2][2])) rotation_matrix = rs.XformRotation1(plane_start, plane_end) matrix = rs.XformMultiply(translation_matrix, rotation_matrix) return [matrix.M00, matrix.M01, matrix.M02, matrix.M03, matrix.M10, matrix.M11, matrix.M12, matrix.M13, matrix.M20, matrix.M21, matrix.M22, matrix.M23]
def rotateAroundLine(p1,p2,p3,q1,q2,q3,theta): #The procedure in this method is outlined by the textbook sinThX = q2/math.sqrt(q2**2 + q3**2) cosThX = q3/math.sqrt(q2**2 + q3**2) sinThY = q1 cosThY = math.sqrt(q2**2 + q3**2) rotation = RhinoScript.XformMultiply(translate(-p1,-p2,-p3), rotateYZ(sinThX,cosThX)) rotation = RhinoScript.XformMultiply(rotation, rotateXZ(-sinThY,cosThY)) rotation = RhinoScript.XformMultiply(rotation, rotateXY(math.sin(theta),math.cos(theta))) rotation = RhinoScript.XformMultiply(rotation, rotateXZ(sinThY,cosThY)) rotation = RhinoScript.XformMultiply(rotation, rotateYZ(-sinThX,cosThX)) rotation = RhinoScript.XformMultiply(rotation, translate(p1,p2,p3)) return rotation
def profileXform(sec, plane, vec): xvec = rs.XformTranslation(vec) cob = rs.XformChangeBasis(plane, rs.WorldXYPlane()) xform = rs.XformMultiply(cob, xvec) return rs.TransformObjects(sec, xform, False)
def rotateXZ(theta): rotation = [[math.cos(theta),0, -math.sin(theta),0], [0,1,0,0], [math.sin(theta),0, math.cos(theta),0], [0,0,0,1]] return rotation def stretch(x, y, z): stc = [[x,0,0,0], [0,y,0,0], [0,0,z,0], [0,0,0,1]] return stc phi = 1.61803398875 turn = rotateXY((2*math.pi)/phi) xyRotation = turn copies = 45 for i in range(copies): t = float(i)/float(copies - 1) xzAngle = t*t*(math.pi*9.0/24.0) + math.pi*1.0/24.0 xzRotation = rotateXZ(xzAngle) widen = stretch(1, 1 + t*t*2.5, 1) tsfm = rhino.XformMultiply(xyRotation, xzRotation) tsfm = rhino.XformMultiply(tsfm, widen) new_obj = rhino.TransformObject(obj, tsfm, copy=True) xyRotation = rhino.XformMultiply(xyRotation, turn)
def main(): # get our curves profile, cross = get_two_curves() if profile is None or cross is None: return ################################################## # get bounding box for cross section cross_bbox = rs.BoundingBox([cross]) cmin, cmax = box_to_points(cross_bbox) cz_range = cmax[2] - cmin[2] cz = 0.5 * (cmax[2] + cmin[2]) c_ctr, _ = rs.CurveAreaCentroid(cross) # make sure it's planar in XY if cz_range > 1e-9: print 'cross section curve should be planar in XY plane' return ################################################## # get bounding box for profile profile_bbox = rs.BoundingBox([profile]) # make sure it's planar in in YZ pmin, pmax = box_to_points(profile_bbox) px_range = pmax[0] - pmin[0] if px_range > 1e-9: print 'profile curve should be planar in YZ plane' return ################################################## # get the point closest to the center for the # cross-section curve r, pc = get_inscribed_radius(cross, c_ctr) ################################################## # get the range of z-values for the profile curve _, _, z0 = pmin _, _, z1 = pmax ################################################## # build list of rings and list of points points = [] ring_pipes = [] # for each level for i in range(num_levels): # get the Z value of the ith plane u = float(i) / (num_levels-1) z = z0 + u*(z1 - z0) # build the i'th plane plane = rs.PlaneFromNormal([0, 0, z], [0, 0, 1], [1, 0, 0]) # find out where the plane intersects the profile curve intersect = rs.PlaneCurveIntersection(plane, profile) # there should be exactly one intersection of type 1 (point) if intersect is None or len(intersect) > 1 or intersect[0][0] != 1: print 'bad intersection' return # get the intersection point pi = intersect[0][1] # get the desired XY radius at this z value ri = abs(pi[1]) # we need to set up some transformations: # translate cross section curve down to z=0 T1 = rs.XformTranslation(mz.vec_mul(list(c_ctr), -1.0)) # scale it along XY by the ratio of radii S1 = rs.XformScale([ri/r, ri/r, 1.0]) # scale a piped cross section along Z by a vertical scale factor S2 = rs.XformScale([1.0, 1.0, ring_vscale]) # translate piped cross section up to our desired z value T2 = rs.XformTranslation([0, 0, z]) # scale and translate cross section curve ci = rs.TransformObject(cross, rs.XformMultiply(S1, T1), copy=True) # pipe it ring = rs.AddPipe(ci, [0, 1], [ring_rad, ring_rad]) # scale vertically and transform up ring = rs.TransformObject(ring, rs.XformMultiply(T2, S2)) # delete the copy of the cross section curve rs.DeleteObject(ci) # add to list of ring pipes ring_pipes.append(ring) # create a rotation by the i'th angle angle_i_deg = i*360.0/num_sides Ri = rs.XformRotation2(angle_i_deg, [0, 0, 1], [0, 0, 0]) # transform the closest point by rotation and scale pci = rs.PointTransform(pc, rs.XformMultiply(rs.XformMultiply(Ri, T2), S1)) # add to list of points points.append(pci) # we have built up a list of points for a single spiral of struts to connect, # now we need to pipe them all together and do the ArrayPolar thing around # the z axis # first build a single spiral of struts strut_pipes = [] for i0 in range(num_levels-1): i1 = i0+1 p0 = points[i0] p1 = points[i1] l01 = rs.AddLine(p0, p1) pipe = rs.AddPipe(l01, [0, 1], [strut_rad, strut_rad], cap=2) rs.DeleteObject(l01) strut_pipes.append(pipe) # then array polar around Z axis all_strut_pipes = [] all_strut_pipes += strut_pipes for j in range(1, num_sides): angle_j_deg = j*360.0/num_sides Rj = rs.XformRotation2(angle_j_deg, [0, 0, 1], [0, 0, 0]) all_strut_pipes += rs.TransformObjects(strut_pipes, Rj, copy=True) # now just select all the objects we created rs.SelectObjects(ring_pipes + all_strut_pipes) # done! print 'yay'
elif c == 'n': #flag for beginning a node spokeCount = 0 nodeNormal = fwdVctr nodeOrthogonal = orthVctr(nodeNormal) randomRotate = random()*2.0*math.pi nodeOrthogonal = RhinoScript.VectorTransform(nodeOrthogonal, rotateAroundVector(nodeNormal,randomRotate)) elif c == 'R': #node spoke rotate spokeCount = spokeCount + 1 for i in range(spokeCount): fwdVctr = RhinoScript.VectorTransform(nodeOrthogonal, rotateAroundVector(nodeNormal,phiangle)) randomRotate = math.acos(random()*math.pi)/2.0 fwdVctr = RhinoScript.VectorTransform(fwdVctr, rotateAroundVector(Rhino.Geometry.Vector3d.CrossProduct(fwdVctr,nodeNormal),randomRotate)) elif c == 'F': #find rotation matrix from old forward vector orthVctr = orthVector(fwdVctr) relativeRotation = RhinoScript.XformMultiply(rotateAroundVector(fwdVctr,turtleRelOr[0]), rotateAroundVector(orthVctr,turtleRelOr[1])) rotationMatrix = RhinoScript.XformMultiply(relativeRotation, rotationMatrix) rotationMatrix = verticalRotate(rotationMatrix, verticality) #find new forward vector from rotation matrix and scale fwdVctr = RhinoScript.VectorTransform(upVctr, rotationMatrix) fwdVctr = RhinoScript.VectorUnitize(fwdVctr) scaleMatrix = ID for i in range(depth): fwdVctr = RhinoScript.VectorScale(fwdVctr, scaleValue) scaleMatrix = RhinoScript.XformMultiply(scaleMatrix, scale(scaleValue)) #add data to transformation stack amalgam = RhinoScript.XformMultiply(translate(turtlePos[0],turtlePos[1],turtlePos[2]), rotationMatrix) amalgam = RhinoScript.XformMultiply(amalgam, scaleMatrix) tsfmStack.append(amalgam)
def FixedFractureGen(n, aspect_ratio=None, sides=None): """ A function to add a fixed number of circles in a cube. It also writes data to fracture data text file for regenerating fracture networks. """ if fracture_shape == 'circle': # initialize a to store fractures fracture_list = [] # a loop to insert the fixed number of fractures for i in range(n): #layer name for the frcature layer_name = "FRACTURE_" + str(i + 1) #create an istance of Fracture class frac = Fracture() #store fracture name frac.fracture_name = layer_name #generate origin for fracture origin = GeneratePoint(boxlength) #store farcture center frac.fracture_center = origin #convert the origin to a plane plane = InclinePlane(origin) #add layer and color rs.AddLayer(layer_name, rs.CreateColor(0, 255, 0)) #make current layer rs.CurrentLayer(layer_name) #insert the fracture in the domain my_circle = rs.AddCircle(plane, radius) #circle_list.append(my_circle) surf = rs.AddPlanarSrf(my_circle) #delete initial fracture drawn which is a curve rs.DeleteObject(my_circle) #save fracture's GUID frac.fracture_GUID = surf[0] #append fracture into fracture list fracture_list.append(frac) elif fracture_shape == 'ellipse': #list to store fracture surface GUIDs fracture_list = [] for i in range(n): #layer name for the frcature layer_name = "FRACTURE_" + str(i + 1) #create an istance of Fracture class frac = Fracture() frac.fracture_name = layer_name #generate fracture origin origin = GeneratePoint(boxlength) frac.fracture_center = origin #plane for fracture plane = InclinePlane(origin) #calculate r_y ry = radius / aspect_ratio #create layer for fracture rs.AddLayer(layer_name, rs.CreateColor(0, 255, 0)) rs.CurrentLayer(layer_name) #draw ellipse fracture = rs.AddEllipse(plane, radius, ry) # write the plane, r_x and r_y to file for re-plotting ##file.write("\n" + str(plane[0]) + "," + str(plane[1]) + "," + str(plane[2]) + "," + str(radius) + ","+ str(ry)) #make fracture a surface frac_surf = rs.AddPlanarSrf(fracture) #delete initial fracture drawn which is a curve rs.DeleteObject(fracture) #append surface GUID to list of fracture surfaces frac.fracture_GUID = frac_surf[0] fracture_list.append(frac) elif fracture_shape == 'polygon': #list to store fracture surface GUIDs fracture_list = [] #write the shape type ##file.write('\npolygon\n') for i in range(n): layer_name = "FRACTURE_" + str(i + 1) frac = Fracture() frac.fracture_name = layer_name #theta in radian theta_rad = (2 * math.pi) / sides #theta in degree (interior angles) theta_deg = theta_rad * (180 / math.pi) #generate origin origin = GeneratePoint(boxlength) frac.fracture_center = origin #create a 3D point object which isn't visible to the rhino document pt_01 = rs.coerce3dvector( [radius + origin[0], origin[1], origin[2]]) #empty list to store all points points = [] #a rotation axis ax = rs.coerce3dvector([0, 0, 1]) #loop to generate points for polygon vertices #file.write("\n") for j in range(sides): #rotation transform with rotation from the origin trans = rs.XformRotation2(theta_deg * j, ax, origin) #transform the original 3D point and append to list points.append(rs.PointTransform(pt_01, trans)) # append the initial point to close the polygon points.append(pt_01) # create layer for fracture # layer_name = "FRACTURE_" + str(i+1) rs.AddLayer(layer_name, rs.CreateColor(0, 255, 0)) rs.CurrentLayer(layer_name) # get GUID of created polygon polygon = rs.AddPolyline(points) # polygon = rs.AddPolyline(points) plane = InclinePlane(origin, boxlength) cob = rs.XformChangeBasis(rs.WorldXYPlane(), plane) shear2d = rs.XformIdentity() shear2d[0, 2] = math.tan(math.radians(45.0)) cob_inverse = rs.XformChangeBasis(plane, rs.WorldXYPlane()) temp = rs.XformMultiply(shear2d, cob) xform = rs.XformMultiply(cob_inverse, temp) fracture = rs.TransformObjects(polygon, xform, False) # make fracture a surface frac_surf = rs.AddPlanarSrf(fracture) # delete initial fracture drawn which is a curve rs.DeleteObject(fracture) frac.fracture_GUID = frac_surf[0] fracture_list.append(frac) return fracture_list
def RedrawNetwork(path): """ A function to reload/regenerate fracture networks. Parameter -------- path: str path where the text file containing fracture data is stored. """ # open text file m = open(path, 'r') # read first line of text file; length of the domain l = m.readline() # convert length to float length = float(l) # read the second line of the domain; shape of the fracture shape = m.readline().split() #corners = ([(0,0,0),(length,0,0),(length,length,0),(0,length,0),(0,0,length),(length,0,length),(length,length,length),(0,length,length)]) #rs.AddBox(corners) # create the domain dom = Domain.Domain(length) # display the domain dom.Show() if shape[0] != 'polygon': # a list to store GUIDs of regenerated fractures frac_list = [] # list to store the x_axis of the fracture plane x_axis = [] # list to store the y_axis of the fracture plane y_axis = [] # list to store the origin of the fracture location origin = [] # list to store the size of fracture size = [] # read file line by line for line in m: # split line by comma words = line.split(",") #if words[0] != 'circle': # append the origin, x_axis and y_axis values in each line origin.append(float(words[0])) origin.append(float(words[1])) origin.append(float(words[2])) x_axis.append(float(words[3])) x_axis.append(float(words[4])) x_axis.append(float(words[5])) y_axis.append(float(words[6])) y_axis.append(float(words[7])) y_axis.append(float(words[8])) size.append(float((words[9]))) # if the shape is ellipse, we have two radii, so append the second radius if shape[0] == 'ellipse': size.append(float((words[10]))) # close file m.close() # display fractures if they are circles/disks if shape[0] == 'circle': n = 0 # go through the lists of origin, x_axis and y_axis # we divide by 3, because the list contains 3 consecutive values # representing a single origin, x_axis or y_axis for i in range(int(len(origin) / 3)): # lists to store the origin, x_axis and y_axis of each fracture o = [] x = [] y = [] # append the origin, x_axis and y_axis of each fracture for j in range(3): o.append(origin[n + j]) x.append(x_axis[n + j]) y.append(y_axis[n + j]) # convert the origin, x_axis and y_axis to a plane plane = rs.PlaneFromFrame(o, x, y) # name the current layer # we are creating layers so that we can trim out of bounds fractures # the function that does this makes use of the layer names layer_name = "FRACTURE_" + str(i + 1) # give the layer a color rs.AddLayer(layer_name, rs.CreateColor(0, 255, 0)) # make layer the current layer rs.CurrentLayer(layer_name) # draw fracture my_disk = rs.AddCircle(plane, size[i]) # convert to a surface surf = rs.AddPlanarSrf(my_disk) #delete initial fracture drawn which is a curve rs.DeleteObject(my_disk) # append fracture frac_list.append(surf) # increment n used for parsing n += 3 # trim out of bounds fractures # the function all creates new fractures at the locations of all # exixting fractures dom.RemoveSurfacesOutsideOfBox(length) # delete all old fractures for frac in frac_list: rs.DeleteObject(frac) dom_frac = dom.my_fractures #get the fractures in the domain #print(dom_frac) #swap old guids with new ones and put new guids in old frac layers #new_frac_guids = Frac.NewFracturesGuids(dom_frac,frac_list) # display fractures if they are ellipse if shape[0] == 'ellipse': # lists to store the origin, x_axis and y_axis of each fracture n = 0 p = 0 q = 1 # go through the lists of origin, x_axis and y_axis # we divide by 3, because the list contains 3 consecutive values # representing a single origin, x_axis or y_axis for i in range(int(len(origin) / 3)): o = [] x = [] y = [] # append the origin, x_axis and y_axis of each fracture for j in range(3): o.append(origin[n + j]) x.append(x_axis[n + j]) y.append(y_axis[n + j]) # convert the origin, x_axis and y_axis to a plane plane = rs.PlaneFromFrame(o, x, y) # name the current layer # we are creating layers so that we can trim out of bounds fractures # the function that does this makes use of the layer names layer_name = "FRACTURE_" + str(i + 1) # give the layer a color rs.AddLayer(layer_name, rs.CreateColor(0, 255, 0)) # make layer current layer rs.CurrentLayer(layer_name) # draw fracture my_frac = rs.AddEllipse(plane, size[i + p], size[i + q]) # convert to a surface from curve surf = rs.AddPlanarSrf(my_frac) # delete initial fracture drawn which is a curve rs.DeleteObject(my_frac) # append fracture frac_list.append(surf) # increment varaiables used for parsing n += 3 p += 1 q += 1 # trim out of bounds fractures dom.RemoveSurfacesOutsideOfBox(length) # delete old fractures for frac in frac_list: rs.DeleteObject(frac) dom_frac = dom.my_fractures if shape[0] == 'polygon': # list to store origin origin = [] # list to store number of sides of each polygon size = [] # list to store the x_axis of the fracture plane x_axis = [] # list to store the y_axis of the fracture plane y_axis = [] # list to store fractures frac_list = [] # list to store points points = [] for line in m: # split each line by comma words = line.split(",") # store the number of sides of the polygon size.append(float(words[-1])) # store the x axis x_axis.extend( (float(words[-7]), float(words[-6]), float(words[-5]))) y_axis.extend( (float(words[-4]), float(words[-3]), float(words[-2]))) # store the origin origin.extend( (float(words[-10]), float(words[-9]), float(words[-8]))) # length of all points on the line # this will ensure we capture lines with disparate points when # generating polygon of different sides ex = int(3 * (size[-1] + 1)) # store all points on the line points.extend((words[:ex])) # close file m.close() # variables to use for parsing n = 0 m = 0 # iterate for the number of fractures generated for i in range(len(size)): # list to store points and origin o = [] x = [] y = [] p = [] # get the origin and axes of the fracture for j in range(3): o.append(origin[n + j]) x.append(x_axis[n + j]) y.append(y_axis[n + j]) # variable for parsing r = 0 # get the points of fracture edges for k in range(int(size[i]) + 1): p.append([]) for l in range(3): p[k].append(float(points[m + l + r])) # increment r r += 3 # increment parsing variables m += ((int(size[i]) + 1) * 3) n += 3 # name the current layer # we are creating layers so that we can trim out of bounds fractures # the function that does this makes use of the layer names layer_name = "FRACTURE_" + str(i + 1) # give the layer a color rs.AddLayer(layer_name, rs.CreateColor(0, 255, 0)) # make layer the current layer rs.CurrentLayer(layer_name) # joing the points poly = rs.AddPolyline(p) # get the plane plane = rs.PlaneFromFrame(o, x, y) # transform fracture to the plane cob = rs.XformChangeBasis(rs.WorldXYPlane(), plane) shear2d = rs.XformIdentity() shear2d[0, 2] = math.tan(math.radians(45.0)) cob_inverse = rs.XformChangeBasis(plane, rs.WorldXYPlane()) temp = rs.XformMultiply(shear2d, cob) xform = rs.XformMultiply(cob_inverse, temp) frac = rs.TransformObjects(poly, xform, False) # convert to a surface surf = rs.AddPlanarSrf(frac) #delete initial fracture drawn which is a curve rs.DeleteObject(frac) frac_list.append(surf) # trim out of bounds fractures # the function all creates new fractures at the locations of all # exixting fractures dom.RemoveSurfacesOutsideOfBox(length) # delete all old fractures for fr in frac_list: rs.DeleteObject(fr) dom_frac = dom.my_fractures return dom_frac
def RandomFractureGen(frac_min, frac_max, radius_min, radius_max, aspect_min=None, aspect_max=None, polysize_min=None, polysize_max=None): """ Funtions to generate fractures of random number and sizes Parameters ---------- frac_min: int minimum number of fractures to generate frac_max: int maximum number of fractures to generate radius_min: float minimum size of fractures radius_max: float maximum number of fractures to generate aspect_min: float minimum aspect ratio fpr ellipses (Default:None) aspect_max: float maximum aspect ratio fpr ellipses (Default:None) polysize_min: int minimum size of polygon (Default:None) polysize_max: int maximum size of polygon (Default:None) """ # randomly determine the number of fractures to generate num_frac = random.randint(frac_min, frac_max) # open file and append to it file = open(path, 'a') if fracture_shape == 'circle': # write the shape type file.write('\ncircle') # initialize list to store fractures fracture_list = [] # loop to generate fractures for i in range(num_frac): # name the layer layer_name = "FRACTURE_" + str(i + 1) # an instance of fracture object frac = Fracture() # get fracture name frac.fracture_name = layer_name # generate fracture center origin = GeneratePoint(boxlength) # store fracture center frac.fracture_center = origin # convert the origin to a plane plane = InclinePlane(origin, boxlength) # add layer and create color for it rs.AddLayer(layer_name, rs.CreateColor(0, 255, 0)) # make layer current layer rs.CurrentLayer(layer_name) # generate fracture size radius = FractureSize(size_dist, radius_min, radius_max) # insert the circle in the domain my_circle = rs.AddCircle(plane, radius) # write the plane and radius to file for re-plotting file.write("\n" + str(plane[0]) + "," + str(plane[1]) + "," + str(plane[2]) + "," + str(radius)) surf = rs.AddPlanarSrf(my_circle) # delete initial fracture drawn which is a curve rs.DeleteObject(my_circle) # set fracture guid into its object frac.fracture_GUID = surf[0] fracture_list.append(frac) elif fracture_shape == 'ellipse': # initialize list to store fractures fracture_list = [] # write the shape type file.write('\nellipse') for i in range(num_frac): # name the layer layer_name = "FRACTURE_" + str(i + 1) # an instance of fracture object frac = Fracture() # get fracture name frac.fracture_name = layer_name # generate fracture center origin = GeneratePoint(boxlength) # store fracture center frac.fracture_center = origin # plane for fracture plane = InclinePlane(origin, boxlength) # randomly generate radius(rx) radius = FractureSize(size_dist, radius_min, radius_max) # randomly generate aspect ratio aspect_ratio = random.randint(aspect_min, aspect_max) # calculate r_y ry = radius / aspect_ratio # add layer with color rs.AddLayer(layer_name, rs.CreateColor(0, 255, 0)) # make current layer rs.CurrentLayer(layer_name) # draw fracture fracture = rs.AddEllipse(plane, radius, ry) # write the plane, r_x and r_y to file for re-plotting file.write("\n" + str(plane[0]) + "," + str(plane[1]) + "," + str(plane[2]) + "," + str(radius) + "," + str(ry)) # make fracture a surface frac_surf = rs.AddPlanarSrf(fracture) # delete initial fracture drawn which is a curve rs.DeleteObject(fracture) # set fracture guid into its object frac.fracture_GUID = frac_surf[0] # append fracture guid to list fracture_list.append(frac) elif fracture_shape == 'polygon': # initialize list to store fractures fracture_list = [] # write the shape type file.write('\npolygon\n') for i in range(num_frac): # name the layer layer_name = "FRACTURE" + str(i + 1) # an instance of fracture class frac = Fracture() # get farcture name frac.fracture_name = layer_name # randomly determine the sides of the polygon sides = random.randint(polysize_min, polysize_max) # theta in radian theta_rad = (2 * math.pi) / sides # theta in degree (interior angles) theta_deg = theta_rad * (180 / math.pi) # generate origin origin = GeneratePoint(boxlength) # save fracture center frac.fracture_center = origin # randomly generate radius(rx) radius = FractureSize(size_dist, radius_min, radius_max) # create a 3D point object which isn't visible to the rhino document pt_01 = rs.coerce3dvector( [radius + origin[0], origin[1], origin[2]]) # empty list to store all points points = [] # a rotation axis ax = rs.coerce3dvector([0, 0, 1]) # loop to generate points for polygon vertices for j in range(sides): # rotation transform with rotation from the origin trans = rs.XformRotation2(theta_deg * j, ax, origin) # transform the original 3D point and append to list points.append(rs.PointTransform(pt_01, trans)) if j == 0: file.write( str(rs.PointTransform(pt_01, trans)[0]) + "," + str(rs.PointTransform(pt_01, trans)[1]) + "," + str(rs.PointTransform(pt_01, trans)[2]) + ",") if j != 0: file.write( str(rs.PointTransform(pt_01, trans)[0]) + "," + str(rs.PointTransform(pt_01, trans)[1]) + "," + str(rs.PointTransform(pt_01, trans)[2]) + ",") # append the initial point to close the polygon points.append(pt_01) file.write( str(pt_01[0]) + "," + str(pt_01[1]) + "," + str(pt_01[2]) + ",") # create layer for fracture layer_name = "FRACTURE_" + str(i + 1) rs.AddLayer(layer_name, rs.CreateColor(0, 255, 0)) rs.CurrentLayer(layer_name) # get GUID of created polygon polygon = rs.AddPolyline(points) # get the plane plane = InclinePlane(origin, boxlength) # transform the polygon to the plane cob = rs.XformChangeBasis(rs.WorldXYPlane(), plane) shear2d = rs.XformIdentity() shear2d[0, 2] = math.tan(math.radians(45.0)) cob_inverse = rs.XformChangeBasis(plane, rs.WorldXYPlane()) temp = rs.XformMultiply(shear2d, cob) xform = rs.XformMultiply(cob_inverse, temp) fracture = rs.TransformObjects(polygon, xform, False) # write to file #file.write(str(origin[0]) + "," + str(origin[1]) + "," + str(origin[2])+ "," ) file.write( str(plane[0]) + "," + str(plane[1]) + "," + str(plane[2]) + "," + str(sides) + "\n") # make fracture a surface frac_surf = rs.AddPlanarSrf(fracture) # delete initial fracture drawn which is a curve rs.DeleteObject(fracture) # set fracture guid into its objects frac.fracture_GUID = frac_surf[0] # append fracture guid to list fracture_list.append(frac) # close file file.close() return fracture_list