def cut_with_polyline(self, pl, startpoint=0): for i, (p1, p2) in enumerate(zip(pl[:-1], pl[1:])): l = norm(p2 - p1) for ik1, k2 in self.cut(p1, p2, startpoint, cut_only_positive=True): ik2 = i + (norm(self[ik1] - p1) / l) yield ik1, ik2
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 area(self): area = 0. if len(self.ribs) == 0: return 0 front = self.get_spanwise(0) back = self.get_spanwise(1) front[0][1] = 0 # Get only half a midrib, if there is... back[0][1] = 0 for i in range(len(front) - 1): area += norm(np.cross(front[i] - front[i + 1], back[i + 1] - front[i + 1])) area += norm(np.cross(back[i] - back[i + 1], back[i] - front[i])) # By this we get twice the area of half the glider :) # http://en.wikipedia.org/wiki/Triangle#Using_vectors return area
def get_segment_lengthes(self): lengths = [] segments = self.get_segments() for s in segments: lengths.append(norm(s)) return lengths
def check(self): # remove zero-length segments index = 0 while index < len(self) - 1: if norm(self[index + 1] - self[index]) < 0.0000001: self.data = np.concatenate([self[:index], self[index + 1:]]) else: index += 1 return self
def noseindex(self): p0 = self.data[0] max_dist = 0 noseindex = 0 for i, p1 in enumerate(self.data): diff = norm(p1 - p0) if diff > max_dist: noseindex = i max_dist = diff return noseindex
def draw(self, graphics): cell, pointnums = super(Arrow, self).draw(graphics) assert len(pointnums) == 2 arrow = vtk.vtkArrowSource() p1, p2 = graphics.get_points(*pointnums) transform = vtk.vtkTransform() transform.Translate(p1) length = norm(p2-p1) transform.Scale(length, length, length)
def _insert_text(self, text): inner, outer = self._get_inner_outer(self.config.rib_text_pos) diff = outer - inner p1 = inner + diff / 2 p2 = p1 + rotation_2d(np.pi / 2).dot(diff) _text = Text(text, p1, p2, size=norm(outer - inner) * 0.5, valign=0) #_text = Text(text, p1, p2, size=0.05) self.plotpart.layers["text"] += _text.get_vectors()
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 trailing_edge_length(self): d = 0 for i, cell in enumerate(self.cells): ballooning = (cell.ballooning[1] + cell.ballooning[-1])/2 vektor = cell.prof1.point(-1) - cell.prof2.point(-1) diff = norm(vektor) * (1 + ballooning) if i == 0 and self.has_center_cell: d += diff else: d += 2 * diff return d
def get_length(self, first=0, second=None): """ Get the (normative) Length of a Part of the Vectorlist. """ if second is None: second = len(self) - 1 direction = sign(float(second - first)) length = 0 next_value = int(first - first % 1 + (direction > 0)) # Just to fasten up if next_value > len(self) and direction < 0: next_value = len(self) elif next_value < 0 < direction: next_value = 0 while next_value * direction < second * direction: length += norm(self[next_value] - self[first]) first = next_value next_value += direction # Fasten up aswell if (next_value > len(self) and direction > 0) or (next_value < 0 and direction < 0): break return length + norm(self[second] - self[first])
def extend(self, start, length): """ Move from a starting point for a given length in direction of the line """ if length == 0: return start direction = sign(length) length = abs(length) next_value = start - start % 1 + (direction > 0) difference = norm(self[start] - self[next_value]) length -= difference # while length > 0: if (next_value > len(self) and direction > 0) or (next_value < 0 and direction < 0): break start = next_value next_value += direction difference = norm(self[next_value] - self[start]) length -= difference # Length is smaller than zero length = length return next_value + direction * length * abs(next_value - start) / difference
def export_apame(glider, path="", midribs=0, numpoints=None, *other): other = glider.copy_complete() if numpoints: other.profile_numpoints = numpoints ribs = other.return_ribs(midribs) v_inf = glider.lineset.v_inf speed = norm(v_inf) glide = np.arctan(v_inf[2] / v_inf[0]) # write config outfile = open(path, "w") outfile.write("APAME input file\nVERSION 3.0\n") outfile.write("AIRSPEED {}\n".format(speed)) outfile.write("DENSITY 1.225\nPRESSURE 1.013e+005\nMACH 0\nCASE_NUM 1\n" ) # TODO: Multiple cases outfile.write(str(math.tan(1 / glide)) + "\n0\n") outfile.write("WINGSPAN " + str(other.span) + "\n") outfile.write("MAC 2") # TODO: Mean Choord outfile.write("SURFACE " + str(other.area) + "\n") outfile.write("ORIGIN\n0 0 0\n") outfile.write("METHOD 0\nERROR 1e-007\nCOLLDIST 1e-007\n") outfile.write("FARFIELD " + str(5) + "\n") # TODO: farfield argument outfile.write( "COLLCALC 0\nVELORDER 2\nRESULTS 1\n1 1 1 1 1 1 1 1 1 1 1 1 1\n\n" ) outfile.write("NODES " + str(len(ribs) * len(ribs[0])) + "\n") for rib in ribs: for point in rib: for coord in point: outfile.write(str(coord) + "\t") outfile.write("\n") outfile.write("\nPANELS " + str((len(ribs) - 1) * (len(ribs[0]) - 1)) + "\n") # TODO: ADD WAKE + Neighbours! for i in range(len(ribs) - 1): for j in range(other.profile_numpoints): # COUNTER-CLOCKWISE! outfile.write("1 {0!s}\t{1!s}\t{2!s}\t{3!s}\n".format( i * len(ribs[0]) + j + 1, (i + 1) * len(ribs[0]) + j + 1, (i + 1) * len(ribs[0]) + j + 2, i * len(ribs[0]) + j + 2)) return outfile.close()
def flatten_list(list1, list2): index_left = index_right = 0 flat_left = [np.array([0, 0])] flat_right = [np.array([norm(list1[0] - list2[0]), 0])] # def which(i, j): # diff = list1[i] - list2[j] # return diff.dot(list1[i+1]-list1[i]+list2[j+1]-list2[j+1]) while True: #while which(index_left, index_right) <= 0 and index_left < len(list1) - 2: # increase left_index if index_left < len(list1) - 1: flat_left.append( point2d(list1[index_left], flat_left[index_left], list2[index_right], flat_right[index_right], list1[index_left + 1])) index_left += 1 #while which(index_left, index_right) >= 0 and index_right < len(list2) - 2: # increase right_index if index_right < len(list2) - 1: flat_right.append( point2d(list1[index_left], flat_left[index_left], list2[index_right], flat_right[index_right], list2[index_right + 1])) index_right += 1 if index_left == len(list1) - 1 and index_right == len(list2) - 1: break # while index_left < len(list1) - 1: # flat_left.append(point2d(list1[index_left], flat_left[index_left], # list2[index_right], flat_right[index_right], # list1[index_left + 1])) # index_left += 1 # # while index_right < len(list2) - 1: # flat_right.append(point2d(list1[index_left], flat_left[index_left], # list2[index_right], flat_right[index_right], # list2[index_right + 1])) # index_right += 1 return PolyLine2D(flat_left), PolyLine2D(flat_right)
def shape_simple(self, cut_center=True): """ Simple (rectangular) shape representation for spline inputs """ last_pos = np.array([0, 0]) # y,z front = [] back = [] x = 0 for rib in self.ribs: width = norm(rib.pos[1:] - last_pos) last_pos = rib.pos[1:] x += width * (rib.pos[1] > 0) # x-value if x == 0: last_pos = np.array([0., 0.]) y_front = -rib.pos[0] + rib.chord * rib.startpos y_back = -rib.pos[0] + rib.chord * (rib.startpos - 1) front.append([x, y_front]) back.append([x, y_back]) return Shape(front, back)
def get_normalized_drag(self): """get the line drag normalized by the velocity ** 2 / 2""" return self.get_drag()[1] / norm(self.v_inf)**2 * 2
def length_projected(self): return norm(self.lower_node.vec_proj - self.upper_node.vec_proj)
def length_no_sag(self): return norm(self.upper_node.vec - self.lower_node.vec)
def tangents(self): tangents = [] for p1, p2 in self.segments: tangents.append((p2 - p1) / norm(p2 - p1)) return np.array(tangents)
def ortho_pressure(self): """ drag per meter (projected) :return: 1/2 * cw * d * v^2 """ return 1 / 2 * self.type.cw * self.type.thickness * norm(self.v_inf) ** 2