def interpolate(self, x, kind): """ Interpolate property at given position x Notes: * The 'kind' parameter determines whether the next or previous property object shall be returned Args: :x: position at which to interpolate :kind: type of interpolation ('prev', 'next') Returns: :inperpol_property: interpolated property """ if not (self.x[0] <= x <= self.x[-1]): raise ValueError("x is out of range") if kind not in ('prev', 'next'): raise ValueError("Invalid return type") for x_val, p_val in zip(pairwise(self.x), pairwise(self.props)): x1, x2 = x_val p1, p2 = p_val if x1 <= x <= x2: if kind == 'prev': return p1 else: return p2
def _make_elements(self): """Create element objects constituting the beam line object""" # Make an interpolator for up up_for_named_nodes = [] for node in self.named_nodes: up_for_named_nodes.append(node['up']) xsi_named_nodes = self.interpolator.get_xsi_support_points() up = PropertyInterpolator(xsi_named_nodes, up_for_named_nodes) # Get list of (relative) points for element nodes point_list = self.interpolator.get_n_points(self.input_nelem + 1) for point1, point2 in pairwise(point_list): xsi1 = point1.xsi xsi2 = point2.xsi xsi = (xsi1 + xsi2) / 2 uid1 = point1.uid uid2 = point2.uid new_element = Element(self, xsi1, xsi2, uid1, uid2, up=up(xsi, 'prev')) self.elements.append(new_element)
def get_nodes_by_xsi(self, xsi): """ Get a beam node for a given xsi position Args: :xsi: relative coordinate in range [0, 1] Returns: :next_node, prev_node: next and previous node """ for prev_node, next_node in pairwise(self.nodes): if prev_node.xsi <= xsi <= next_node.xsi: return prev_node, next_node return None, None
def _make_table(self): """ Create a for interpolation Table contents: {support point} {relative position xsi} """ self.interpol_table.append([self.sup_points[0], 0, self.point_uids[0]]) idx = 1 for p1, p2 in pairwise(self.sup_points): self.length += np.linalg.norm(p2 - p1) self.interpol_table.append([p2, self.length, self.point_uids[idx]]) idx += 1 for i in range(len(self.interpol_table)): self.interpol_table[i][1] /= self.length
def interpolate(self, xsi): """ Return a interpolated point at given xsi position Args: :xsi: relative position Returns: :point: interpolated point """ if not 0 <= xsi <= 1: raise ValueError("xsi must be in range [0, 1]") for entry1, entry2 in pairwise(self.interpol_table): p1, xsi1, _ = entry1 p2, xsi2, _ = entry2 if xsi1 <= xsi <= xsi2: xsi -= xsi1 xsi /= (xsi2 - xsi1) return p1 + xsi*(p2 - p1)