def get_preferred_direction(self, beam): # Obtain the moment vector u1, u2, u3 = beam.global_default_axes() m11, m22, m33 = self.get_moment_magnitudes(beam.name) # Quick debugging - making sure the torsion doesn't get too high if not helpers.compare(m11, 0, 4): #pdb.set_trace() pass # Sum m22 and m33 (m11 is torsion, which doesn't play a role in the direction) moment_vector = helpers.sum_vectors(helpers.scale(m22, u2), helpers.scale(m33, u3)) ''' Cross axis-1 with the moment vector to obtain the positive clockwise direction This keeps the overall magnitude of moment_vector since u1 is a unit vector We are always attempting to repair further up the broken beam (closer to the j-end). The cross will always give us the vector in the right direction if we do it this way. ''' twist_direction = helpers.cross(moment_vector, u1) # Project the twist direction onto the xy-plane and normalize to have a # maximum of 45 degree approach (or, as specified in the variables.py) # depending on the ratio of moment magnitude to max_magnitude xy_change = (twist_direction[0], twist_direction[1], 0) # The rotation is parallel to the z-axis, so we don't add disturbance if helpers.compare(helpers.length(xy_change), 0): # Return the normal direction - which way is the beam leaning??? return super(MomentAwareBuilder, self).get_preferred_direction(beam) # We know the direction in which the beam is turning else: # Get direction of travel (this is a unit vector) travel = super(MomentAwareBuilder, self).get_preferred_direction(beam) # Normalize twist to the maximum moment of force -- structure_check normal = helpers.normalize(xy_change, BConstants.beam['structure_check']) # The beam is vertical - check to see how large the normalized moment is if travel is None: # The change is relatively small, so ignore it if helpers.length(normal) <= helpers.ratio( BConstants.beam['verticality_angle']): return travel else: return helpers.make_unit(normal) else: scalar = 1 / helpers.ratio(BConstants.beam['moment_angle_max']) scaled_travel = helpers.scale(scalar, travel) return helpesr.make_unit( helpers.sum_vectors(normal, scaled_travel))
def global_default_axes(self): ''' Returns the default local axes. Later on we might incorporate the ability to return rotated axes. ''' axis_1 = helpers.make_unit( helpers.make_vector(self.endpoints.i, self.endpoints.j)) vertical = (math.sin( math.radians(helpers.smallest_angle(axis_1, (0, 0, 1)))) <= 0.001) # Break up axis_1 into unit component vectors on 1-2 plane, along with # their maginitudes u1, u2 = (axis_1[0], axis_1[1], 0), (0, 0, axis_1[2]) l1, l2 = helpers.length(u1), helpers.length(u2) u1 = helpers.make_unit(u1) if not helpers.compare(l1, 0) else (1, 1, 0) u2 = helpers.make_unit(u2) if not helpers.compare(l2, 0) else (0, 0, 1) # Calculate axis_2 by negating and flipping componenet vectors of axis_1 axis_2 = (1, 0, 0) if vertical else helpers.make_unit( helpers.sum_vectors(helpers.scale(-1 * l2, u1), helpers.scale(l1, u2))) # Make it have a positive z-component axis_2 = axis_2 if axis_2[2] > 0 else helpers.scale(-1, axis_2) # Calculate axis_3 by crossing axis 1 with axis 2 (according to right hand # rule) axis_3 = helpers.cross(axis_1, axis_2) axis_3 = helpers.make_unit( (axis_3[0], axis_3[1], 0)) if vertical else axis_3 # Sanity checks # Unit length assert helpers.compare(helpers.length(axis_3), 1) # On the x-y plane assert helpers.compare(axis_3[2], 0) return axis_1, axis_2, axis_3
def global_default_axes(self): ''' Returns the default local axes. Later on we might incorporate the ability to return rotated axes. ''' axis_1 = helpers.make_unit(helpers.make_vector(self.endpoints.i, self.endpoints.j)) vertical = (math.sin(math.radians(helpers.smallest_angle(axis_1,(0,0,1)))) <= 0.001) # Break up axis_1 into unit component vectors on 1-2 plane, along with # their maginitudes u1, u2 = (axis_1[0],axis_1[1],0),(0,0,axis_1[2]) l1,l2 = helpers.length(u1), helpers.length(u2) u1 = helpers.make_unit(u1) if not helpers.compare(l1,0) else (1,1,0) u2 = helpers.make_unit(u2) if not helpers.compare(l2,0) else (0,0,1) # Calculate axis_2 by negating and flipping componenet vectors of axis_1 axis_2 = (1,0,0) if vertical else helpers.make_unit(helpers.sum_vectors( helpers.scale(-1 * l2,u1),helpers.scale(l1,u2))) # Make it have a positive z-component axis_2 = axis_2 if axis_2[2] > 0 else helpers.scale(-1,axis_2) # Calculate axis_3 by crossing axis 1 with axis 2 (according to right hand # rule) axis_3 = helpers.cross(axis_1,axis_2) axis_3 = helpers.make_unit((axis_3[0],axis_3[1],0)) if vertical else axis_3 # Sanity checks # Unit length assert helpers.compare(helpers.length(axis_3),1) # On the x-y plane assert helpers.compare(axis_3[2],0) return axis_1,axis_2,axis_3