def calc_forces(self, start_lines): for line_lower in start_lines: upper_node = line_lower.upper_node vec = line_lower.diff_vector if line_lower.upper_node.type != 2: # not a gallery line # recursive force-calculation # setting the force from top to down lines_upper = self.get_upper_connected_lines(upper_node) self.calc_forces(lines_upper) force = np.zeros(3) for line in lines_upper: if line.force is None: print("error line force not set: {}".format(line)) else: force += line.force * line.diff_vector # vec = line_lower.upper_node.vec - line_lower.lower_node.vec line_lower.force = norm(np.dot(force, normalize(vec))) else: force = line_lower.upper_node.force force_projected = proj_force(force, normalize(vec)) if force_projected is None: print("shit", line_lower.upper_node.name) line_lower.force = 10 else: line_lower.force = norm(force_projected)
def get_tangential_comp(self, line, pos_vec): # upper_lines = self.get_upper_connected_lines(line.upper_node) # first we try to use already computed forces # and shift the upper node by residual force # we have to make sure to not overcompansate the residual force if line.has_geo and line.force is not None: r = self.get_residual_force(line.upper_node) s = 0 for con_line in self.get_connected_lines(line.upper_node): s += con_line.get_correction_influence(r) # the additional factor is needed for stability. A better aproach would be to # compute the compansation factor s with a system of linear equation. The movement # of the upper node has impact on the compansation of residual force # of the lower node (and the other way). return normalize(line.diff_vector + r / s * 0.3) # if norm(r) == 0: # return line.diff_vector # z = r / np.linalg.norm(r) # v0 = line.upper_node.vec - line.lower_node.vec # s = norm(r) * (norm(v0) / line.force - v0.dot(z)) # return normalize(v0 + s * z * 0.1) else: # if there are no computed forces available, use all the uppermost forces to compute # the direction of the line tangent = np.array([0., 0., 0.]) upper_node = self.get_upper_influence_nodes(line) for node in upper_node: tangent += node.calc_force_infl(pos_vec) return normalize(tangent)
def norm_segment_vectors(self): """ return all the normals based on the segments of the data: len(data) - 1 == len(normals) """ rotate = lambda x: normalize(x).dot([[0, -1], [1, 0]]) normvectors = [] for p1, p2 in self.segments: normvectors.append(rotate(normalize(p2 - p1))) return np.array(normvectors)
def __init__(self, direction=None): if direction is None: direction = [1., 0., 0.] if len(direction) == 2: x, y = normalize(direction) self.matrix = np.array([[1 - 2 * x**2, -2 * x * y], [-2 * x * y, 1 - 2 * y**2]]) else: x, y, z = normalize(direction) self.matrix = np.array([[1 - 2 * x**2, -2 * x * y, -2 * x * z], [-2 * x * y, 1 - 2 * y**2, -2 * y * z], [-2 * x * z, -2 * y * z, 1 - 2 * z**2]])
def point2d(p1_3d, p1_2d, p2_3d, p2_2d, point_3d): """Returns a third points position relative to two known points (3D+2D)""" # diffwise diff_3d = normalize(p2_3d - p1_3d) diff_2d = normalize(p2_2d - p1_2d) diff_point = point_3d - p1_3d point_2d = p1_2d + diff_2d * diff_3d.dot(diff_point) # length-wise diff_3d = normalize(diff_point - diff_3d * diff_3d.dot(diff_point)) diff_2d = diff_2d.dot([[0, 1], [-1, 0]]) # Rotate 90deg return np.array(point_2d + diff_2d * diff_3d.dot(diff_point))
def normvectors(self): layer = self.projection_layer profnorm = layer.normvector get_normvector = lambda x: normalize(np.cross(x, profnorm)) vectors = [get_normvector(self.data[1] - self.data[0])] for i in range(1, len(self.data) - 1): vectors.append( get_normvector( normalize(self.data[i + 1] - self.data[i]) + normalize(self.data[i] - self.data[i - 1]))) vectors.append(get_normvector(self.data[-1] - self.data[-2])) return vectors
def apply(self, inner_lists, outer_left, outer_right, amount_3d=None): p1, p2 = self.get_p1_p2(inner_lists, amount_3d) indices = self._get_indices(inner_lists, amount_3d) normvector = normalize(rotation_2d(math.pi / 2).dot(p1 - p2)) leftcut_index = next( outer_left.cut(p1, p2, inner_lists[0][1], extrapolate=True)) rightcut_index = next( outer_right.cut(p1, p2, inner_lists[-1][1], extrapolate=True)) index_left = leftcut_index[0] index_right = rightcut_index[0] leftcut = outer_left[index_left] rightcut = outer_right[index_right] leftcut_index_2 = outer_left.cut(p1 - normvector * self.amount, p2 - normvector * self.amount, inner_lists[0][1], extrapolate=True) rightcut_index_2 = outer_right.cut(p1 - normvector * self.amount, p2 - normvector * self.amount, inner_lists[-1][1], extrapolate=True) leftcut_2 = outer_left[next(leftcut_index_2)[0]] rightcut_2 = outer_right[next(rightcut_index_2)[0]] diff_l, diff_r = leftcut - leftcut_2, rightcut - rightcut_2 curve = PolyLine2D( [leftcut, leftcut + diff_l, rightcut + diff_r, rightcut]) return CutResult(curve, leftcut_index[0], rightcut_index[0], indices)
def projection_layer(self): """ Projection Layer of profile_3d """ p1 = self.data[0] diff = [p - p1 for p in self.data] xvect = normalize(-diff[self.noseindex]) yvect = np.array([0, 0, 0]) for i in range(len(diff)): sign = 1 - 2 * (i > self.noseindex) yvect = yvect + sign * (diff[i] - xvect * xvect.dot(diff[i])) yvect = normalize(yvect) return Plane(self.data[self.noseindex], xvect, yvect)
def apply(self, inner_lists, outer_left, outer_right, amount_3d=None): #p1 = inner_lists[0][0][inner_lists[0][1]] # [[list1,pos1],[list2,pos2],...] #p2 = inner_lists[-1][0][inner_lists[-1][1]] p1, p2 = self.get_p1_p2(inner_lists, amount_3d) indices = self._get_indices(inner_lists, amount_3d) normvector = normalize(rotation_2d(math.pi / 2).dot(p1 - p2)) newlist = [] # todo: sort by distance cuts_left = list( outer_left.cut(p1, p2, inner_lists[0][1], extrapolate=True)) cuts_left.sort(key=lambda cut: abs(cut[1])) leftcut_index = cuts_left[0][0] leftcut = outer_left[leftcut_index] newlist.append(leftcut) newlist.append(leftcut + normvector * self.amount) for thislist in inner_lists: newlist.append(thislist[0][thislist[1]] + normvector * self.amount) cuts_right = list( outer_right.cut(p1, p2, inner_lists[-1][1], extrapolate=True)) cuts_right.sort(key=lambda cut: abs(cut[1])) rightcut_index = cuts_right[0][0] rightcut = outer_right[rightcut_index] newlist.append(rightcut + normvector * self.amount) newlist.append(rightcut) curve = PolyLine2D(newlist) return CutResult(curve, leftcut_index, rightcut_index, indices)
def tangents(self): second = self.data[0] third = self.data[1] tangents = [normalize(third - second)] for element in self.data[2:]: first = second second = third third = element tangent = np.array([0, 0, 0]) for vec in [third - second, second - first]: try: tangent = tangent + normalize(vec) except ValueError: # zero-length vector pass tangents.append(tangent) tangents.append(normalize(third - second)) return tangents
def calc_force_infl(self, vec): v = np.array(vec) force = proj_force(self.force, self.vec - v) if force is None: print(self.name) print(self.vec-v, self.force) force = 0.00001 return normalize(self.vec - v) * force
def mirror(self, p1, p2): """ Mirror against a line through p1 and p2 """ p1 = np.array(p1) p2 = np.array(p2) normvector = normalize(np.array(p1 - p2).dot([[0, -1], [1, 0]])) self.data = [ point - 2 * normvector.dot(point - p1) * normvector for point in self.data ] return self
def normvectors(self): #RENAME: norm_point_vectors? """ Return Normvectors to the List-Line, heading rhs this property returns a normal for every point, approximated by the 2 neighbour points (len(data) == len(normals)) """ rotate = lambda x: normalize(x).dot([[0, -1], [1, 0]]) normvectors = [rotate(self.data[1] - self.data[0])] for j in range(1, len(self.data) - 1): normvectors.append( #rotate(normalize(self.data[j + 1] - self.data[j]) + normalize(self.data[j] - self.data[j - 1]))) rotate(self.data[j + 1] - self.data[j - 1])) normvectors.append(rotate(self.data[-1] - self.data[-2])) return normvectors
def apply(self, inner_lists, outer_left, outer_right, amount_3d=None): p1, p2 = self.get_p1_p2(inner_lists, amount_3d) indices = self._get_indices(inner_lists, amount_3d) normvector = normalize(rotation_2d(math.pi / 2).dot(p1 - p2)) left_start_index = next( outer_left.cut(p1, p2, inner_lists[0][1], extrapolate=True))[0] right_start_index = next( outer_right.cut(p1, p2, inner_lists[-1][1], extrapolate=True))[0] pp1 = p1 - normvector * self.amount pp2 = p2 - normvector * self.amount left_end_index = next( outer_left.cut(pp1, pp2, inner_lists[0][1], extrapolate=True))[0] right_end_index = next( outer_right.cut(pp1, pp2, inner_lists[-1][1], extrapolate=True))[0] left_start = outer_left[left_start_index] left_end = outer_left[left_end_index] right_start = outer_right[right_start_index] right_end = outer_right[right_end_index] left_piece = outer_left[left_end_index:left_start_index] right_piece = outer_right[right_end_index:right_start_index] left_piece_mirrored = left_piece[::-1] right_piece_mirrored = right_piece[::-1] left_piece_mirrored.mirror(p1, p2) right_piece_mirrored.mirror(p1, p2) # mirror to (p1-p2) -> p'=p-2*(p.normvector) last_left, last_right = left_start, right_start new_left, new_right = PolyLine2D(None), PolyLine2D(None) for i in range(self.num_folds): left_this = left_piece if i % 2 else left_piece_mirrored right_this = right_piece if i % 2 else right_piece_mirrored left_this.move(last_left - left_this[0]) right_this.move(last_right - right_this[0]) new_left += left_this new_right += right_this last_left, last_right = new_left.data[-1], new_right.data[-1] curve = new_left + new_right[::-1] return CutResult(curve, left_start_index, right_start_index, indices)
def apply(self, inner_lists, outer_left, outer_right, amount_3d=None): """ :param inner_lists: :param outer_left: :param outer_right: :param amount_3d: list of 3d-shaping amounts :return: """ inner_new = [] point_list = [] for offset, lst in zip(amount_3d, inner_lists): curve, ik = lst ik_new = curve.extend(ik, offset) inner_new.append([curve, ik_new]) p1, p2 = self.get_p1_p2(inner_lists, amount_3d) normvector = normalize(rotation_2d(math.pi / 2).dot(p1 - p2)) leftcut_index = next( outer_left.cut(p1, p2, inner_lists[0][1], extrapolate=True)) rightcut_index = next( outer_right.cut(p1, p2, inner_lists[-1][1], extrapolate=True)) index_left = leftcut_index[0] index_right = rightcut_index[0] leftcut = outer_left[index_left] rightcut = outer_right[index_right] point_list.append(leftcut) point_list.append(leftcut + normvector * self.amount) for curve, ik in inner_new: point_list.append(curve[ik] + normvector * self.amount) point_list.append(rightcut + normvector * self.amount) point_list.append(rightcut) curve = PolyLine2D(point_list) return CutResult(curve, index_left, index_right, [x[1] for x in inner_new])
def add_stuff(self, amount): """ Shift the whole line for a given amount (->Sewing allowance) """ # cos(vectorangle(a,b)) = (a1 b1+a2 b2)/Sqrt[(a1^2+a2^2) (b1^2+b2^2)] newlist = [] second = self.data[0] third = self.data[1] newlist.append(second + self.norm_segment_vectors[0] * amount) for i in range(1, len(self.data) - 1): first = second second = third third = self.data[i + 1] d1 = second - first d2 = third - second cosphi = d1.dot(d2) / np.sqrt(d1.dot(d1) * d2.dot(d2)) coresize = 1e-8 if cosphi > 0.9999 or norm(d1) < coresize or norm(d2) < coresize: newlist.append(second + self.normvectors[i] * amount / cosphi) elif cosphi < -0.9999: # this is true if the direction changes 180 degree n1 = self.norm_segment_vectors[i - 1] n2 = self.norm_segment_vectors[i] newlist.append(second + self.norm_segment_vectors[i - 1] * amount) newlist.append(second + self.norm_segment_vectors[i] * amount) else: n1 = self.norm_segment_vectors[i - 1] n2 = self.norm_segment_vectors[i] sign = -1. + 2. * (d2.dot(n1) > 0) phi = np.arccos(n1.dot(n2)) d1 = normalize(d1) ext_vec = n1 - sign * d1 * np.tan(phi / 2) newlist.append(second + ext_vec * amount) # newlist.append(cut(a, b, c, d)[0]) newlist.append(third + self.norm_segment_vectors[-1] * amount) self.data = newlist return self
def get_vectors(self, replace_unknown=True): # todo: add valign (space) vectors = [] diff = (self.p2 - self.p1) / len(self.text) if self.size is not None: diff = normalize(diff) * self.size if self.align == "left": p1 = self.p1.copy() elif self.align == "center": p1 = self.p1 + (self.p2 - self.p1) / 2 - len(self.text) / 2 * diff elif self.align == "right": p1 = self.p2 - len(self.text) * diff else: raise ValueError r_x, r_y = diff[0], diff[1] rot = np.array([[r_x, -r_y * self.height], [r_y, r_x * self.height]]) p1 += np.array([-r_y, r_x]) * (self.valign - 0.5) for letter in self.text.upper(): if letter not in text_vectors: if replace_unknown: letter = "_" else: raise KeyError( "Letter {} from word '{}' not available".format( letter, self.text.upper())) if text_vectors[letter]: vectors.append( PolyLine2D([p1 + rot.dot(p) for p in text_vectors[letter]], name="text")) p1 += diff return vectors
def diff_vector(self): """ Line Direction vector (normalized) :return: """ return normalize(self.upper_node.vec - self.lower_node.vec)
def normalize(self): self.v1 = normalize(self.v1) self.v2 = normalize(self.v2 - self.v1 * self.v1.dot(self.v2))
def diff_vector_projected(self): return normalize(self.upper_node.vec_proj - self.lower_node.vec_proj)
def v_inf_0(self): return normalize(self.v_inf)
inputfile = os.path.abspath(sys.argv[1]) destfile = os.path.dirname(inputfile) + "/geometry.obj" glider = Glider.import_geometry(inputfile) for cell in glider.cells: pass #cell.miniribs.append(openglider.Ribs.MiniRib(0.5, 0.7)) numpoints = int(sys.argv[3]) if numpoints == 0: numpoints = None else: glider.profile_numpoints = numpoints print("numpoints: ", numpoints) midribs = int(sys.argv[2]) print("midribs: ", midribs) glider.export_3d(destfile, midribs=midribs, numpoints=numpoints) # Print v_inf, ca_projection, cw_projection alpha = math.atan(1 / glider.ribs[0].glide) v = glider.data["GESCHWINDIGKEIT"] v_inf = [-math.cos(alpha) * v, 0, -math.sin(alpha) * v] ca = normalize([-v_inf[2], 0, v_inf[0]]) print("v_inf ", v_inf) print("ca: ", ca) print("cw: ", normalize(v_inf)) else: print( "please give me an input file + number of midribs + numpoints (0=Original)" )