def __init__(self, bandgap=555, origin=(0, 0, 0), size=(1, 1, 1), shape="box"): super(Channel, self).__init__() self.origin = np.array(origin) self.size = np.array(size) self.volume = 1 if shape == "box": self.shape = Box(origin=origin, extent=np.array(origin) + np.array(size)) for coord in size: self.volume *= coord elif shape == "cylinder": # takes radius, length # The following is a little workaround to convert origin, size into cylinder (radius, length) descriptors # Axis is based on the longest direction among the size (x,y,z) axis = np.argmax(size) # Length is the value of the longest axis of size length = np.amax(size) # Radius is the average of the other two coordinates divided by two (radius, not diameter!) radius = np.average(np.delete(size, axis)) / 2 # Div. by 2 cause what's given it's the diameter # Cylinder volume formula self.volume = math.pi * radius ** 2 * length self.shape = Cylinder(radius=radius, length=length) # For CSG first rotation then translation (assuming scaling is not needed) if axis == 0: # Z to X Rotation needed self.shape.append_transform(tf.rotation_matrix(math.pi / 2.0, [0, 1, 0])) elif axis == 1: # Z to Y Rotation needed self.shape.append_transform(tf.rotation_matrix(-math.pi / 2.0, [1, 0, 0])) self.shape.append_transform(tf.translation_matrix(origin)) else: self.logger.warn("The channel shape is invalid (neither box nor cylinder. It was " + str(shape)) raise Exception("Channel has invalid shape") self.material = SimpleMaterial(bandgap) self.name = "Channel"
def __init__(self, bandgap=555, base=1, alpha=np.pi / 3, beta=np.pi / 3, length=1): super(Prism, self).__init__() h = base * (1 / np.tan(alpha) + 1 / np.tan(alpha)) box0 = Box(origin=(0, 0, 0), extent=(base, h, length)) box1 = Box(origin=(0, 0, 0), extent=(h / np.sin(alpha), h, length)) box1.append_transform(tf.rotation_matrix(alpha, (0, 0, 1))) box2 = Box(origin=(base, 0, 0), extent=(base + h, h / np.sin(beta), h, length)) box2.append_transform(tf.rotation_matrix(np.pi / 2 - beta, (0, 0, 1))) step1 = CSGsub(box0, box1) step2 = CSGsub(step1, box2) self.shape = step2 self.material = SimpleMaterial(bandgap)
def transform_direction(direction, transform): angle, axis, point = tf.rotation_from_matrix(transform) rotation_transform = tf.rotation_matrix(angle, axis) return np.array( np.dot(rotation_transform, np.matrix(np.concatenate( (direction, [1.]))).transpose()).transpose()[0, 0:3]).squeeze()
def transform_direction(direction, transform): try: rotation_angle, rotation_axis, point = tf.rotation_from_matrix(transform) except ValueError: if tf.is_same_transform(tf.identity_matrix() * -1, transform): # The ray direction needs to be reversed return np.array(direction) * -1. rotation_transform = tf.rotation_matrix(rotation_angle, rotation_axis) return np.array(np.dot(rotation_transform, np.matrix(np.concatenate((direction, [1.]))).transpose()).transpose()[0,0:3]).squeeze()
def rotation_matrix_from_vector_alignment(before, after): """ :param before: vector before rotation :param after: vector after rotation :return: rotation matrix """ """ >>> # General input/output test >>> V1 = norm(np.random.random(3)) >>> V2 = norm([1, 1, 1]) >>> R = rotation_matrix_from_vector_alignment(V1, V2) >>> V3 = transform_direction(V1, R) >>> cmp_points(V2, V3) True >>> # Catch the special case in which we cannot take the cross product >>> V1 = [0, 0, 1] >>> V2 = [0, 0, 1] >>> R = rotation_matrix_from_vector_alignment(V1, V2) >>> V3 = transform_direction(V1, R) >>> cmp_points(V2, V3) True >>> # Catch the special case in which we cannot take the cross product >>> V1 = [0, 0, 1] >>> V2 = [0, 0, -1] >>> R = rotation_matrix_from_vector_alignment(V1, V2) >>> V3 = transform_direction(V1, R) >>> cmp_points(V2, V3) True """ # The angle between the vectors must not be 0 or 180 (i.e. so we can take a cross product) # import pdb; pdb.set_trace() the_dot = np.dot(before, after) if cmp_floats(the_dot, 1.): # Vectors are parallel return tf.identity_matrix() if cmp_floats(the_dot, -1.): # Vectors are anti-parallel # print "Vectors are anti-parallel this might crash." return tf.identity_matrix() * -1. rotation_axis = np.cross(before, after) # get the axis of rotation rotation_angle = np.arccos(np.dot(before, after)) # get the rotation angle return rotation_matrix(rotation_angle, rotation_axis)
def rotate(self, angle, axis): self.shape.append_transform(tf.rotation_matrix(angle, axis))
def rotate(self, angle, axis): self.shape.append_transform(tf.rotation_matrix(angle, axis))
def transform_direction(direction, transform): angle, axis, point = tf.rotation_from_matrix(transform) rotation_transform = tf.rotation_matrix(angle, axis) return np.array(np.dot(rotation_transform, np.matrix(np.concatenate((direction, [1.]))).transpose()).transpose()[0, 0:3]).squeeze()