def render_nbodysystem(a, tup, ps, vs, paths): """ Args: a: param between 0 and 1 -> time tup: tuple returned from solution function (t, vels, poss) ps: list of graphical points """ t = np.array(tup[0]) vels = tup[1] poss = tup[2] duration = max(t) assert duration == stop_time # display one out of the discrete calculated positions, the closest one to the time in the sequence i_to_display = np.where(t <= a * duration)[0][-1] # import ipdb; ipdb.set_trace() # noqa BREAKPOINT for n in range(num_of_bodies): # cut the vector down/extend the vector to a 3d vector, since you can't plot more or less than 3d # import ipdb; ipdb.set_trace() # noqa BREAKPOINT pos_of_particle_np = math_utils.get_3d_vec_from_nd_vec( poss[n][i_to_display]) pos_of_particle = math_utils.np_to_p3d_Vec3(pos_of_particle_np) vel_of_particle_np = math_utils.get_3d_vec_from_nd_vec( vels[n][i_to_display]) vel_of_particle = math_utils.np_to_p3d_Vec3(vel_of_particle_np) ps[n].setPos(pos_of_particle) # plot the velocity vectors vs[n].setTailPoint(pos_of_particle) vel_vector_to_plot = pos_of_particle + vel_of_particle if np.linalg.norm(vel_of_particle_np) >= 1: vel_vector_to_plot = math_utils.np_to_p3d_Vec3( pos_of_particle_np + math_utils.normalize(vel_of_particle_np) * np.log(np.linalg.norm(vel_of_particle_np))) vs[n].setTipPoint(vel_vector_to_plot) # trace out the paths over time paths[n].extendCoords([pos_of_particle_np]) pass
def update_alignment(self): """ """ pos_for_x = math_utils.p3d_to_np( Frame2d.axis_direction_vectors[0]) * Ticks.get_tick_pos_along_axis( self.width, self.axes_ticks_numbers[0], 0.0) pos_for_y = math_utils.p3d_to_np( Frame2d.axis_direction_vectors[1]) * Ticks.get_tick_pos_along_axis( self.height, self.axes_ticks_numbers[1], 0.0) pos_tmp = math_utils.p3d_to_np(pos_for_y) + math_utils.p3d_to_np( pos_for_x) for line in self.linesin2dframe.lines: x_scale = self.get_p3d_to_frame_unit_length_scaling_factor(0) y_scale = self.get_p3d_to_frame_unit_length_scaling_factor(1) # print("x_scale, y_scale: ", x_scale, y_scale) cond = np.abs(x_scale) > 1e-8 and np.abs(y_scale) > 1e-8 if cond: line.setScale(x_scale, 1., y_scale) line.setPos(math_utils.np_to_p3d_Vec3(pos_tmp)) else: print( "scaling by too low is not supported by p3d, do it differently!" ) self.clear_plot()
def set_cursor_position(self, a): """ """ cursor_pos = math_utils.np_to_p3d_Vec3( math_utils.p3d_to_np(self.get_v1()) + a * (math_utils.p3d_to_np(self.get_v2()) - math_utils.p3d_to_np(self.get_v1()))) self.p_c.setPos(cursor_pos)
def get_a_param(self, c2): """ a is between 0 and 1 and represents a time if multiplied by the duration. FIXME: replace getTail/TipPoints with other stuff. """ t = 1. - ( np.linalg.norm( self.edge_graphics.line.getTailPoint() - math_utils.np_to_p3d_Vec3(c2)) / np.linalg.norm( self.edge_graphics.line.getTailPoint() - self.edge_graphics.line.getTipPoint())) return t
def update_while_moving_function(self, s_a, v1, v_dir, p_c, line): # logical, given: # for the current sequence: # s_a: parameter between 0 and 1 for the time between the sequence's current start and end points # s_l: fixed length of what length a sequence should have (choose a reasonable length, corresponding to a time of maybe 10 seconds, after that, start a new (always finite) sequence) # s_dur: fixed duration of the sequence # EdgeRecorder.time_ind=1 (s), (time corresponding to the length of the hint line at start of recording), # v1 (branch point), # v_dir (direction of branching), # lps_rate (length per second rate of the player/recorder) # graphical: p1, p2, p_c, line # asked (logical): # the length of the line at the covered_time (line always just keeps increasing in size, not separate segments). Time in seconds is extracted from s_a (given) self.state.set_s_a(s_a) # update s_a covered_time = s_a * (EdgeRecorder.s_l / EdgePlayer.lps_rate) covered_length = EdgeRecorder.s_l * s_a len_ind = EdgeRecorder.time_ind * EdgePlayer.lps_rate s_a_ind = EdgeRecorder.time_ind * EdgePlayer.lps_rate / EdgeRecorder.s_l if s_a <= s_a_ind: line.setTipPoint(math_utils.np_to_p3d_Vec3(len_ind * v_dir + v1)) elif s_a > s_a_ind: line.setTipPoint( math_utils.np_to_p3d_Vec3(covered_length * v_dir + v1)) else: print("invalid value of s_a: ", s_a) exit(1) line.setTailPoint(math_utils.np_to_p3d_Vec3(v1)) # set cursor point: cursor_pos = math_utils.np_to_p3d_Vec3(covered_length * v_dir + v1) p_c.setPos(cursor_pos) # update the label position (which should be pinned to the (self.p_c), which gets set one line above) self.recorder_label.setPos(*tuple(cursor_pos))
def render_hints(self): """ render various on-hover things: - cursors - time labels """ if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() ray_direction, ray_aufpunkt = cameraray.getCameraMouseRay( self.cameragear.camera, base.mouseWatcherNode.getMouse()) r1 = ray_aufpunkt e1 = ray_direction closestedge = None d_min = float('inf') # points of shortest edge_length c1_min = None c2_min = None for edge in self.draggablegraph.graph_edges: # find closest line (infinite straight) r2 = edge.getTailPoint() edge_p1 = r2 edge_p2 = edge.getTipPoint() e2 = edge_p2 - edge_p1 # direction vector for edge infinite straight line d = np.abs(math_utils.shortestDistanceBetweenTwoStraightInfiniteLines(r1, r2, e1, e2)) c1, c2 = math_utils.getPointsOfShortestDistanceBetweenTwoStraightInfiniteLines( r1, r2, e1, e2) # only count this edge if the vector of shortest edge_length lies in-between the # start and end points of the line # if d is not None: # if d_min is None: # d_min = d # if closestedge is None: # closestedge = edge if c1_min is None: c1_min = c1 if c2_min is None: c2_min = c2 # conditions for closest edge # - d < d_min # - the line segment of shortest edge_length touches the edge's line within the # two node points of the edge: # if d < d_min and math_utils.isPointBetweenTwoPoints(edge_p1, edge_p2, c1): d_min = d closestedge = edge c1_min = c1 c2_min = c2 self.shortest_distance_line.setTipPoint(math_utils.np_to_p3d_Vec3(c1)) self.shortest_distance_line.setTailPoint(math_utils.np_to_p3d_Vec3(c2)) self.shortest_distance_line.show() # -- set the time label # ---- set the position of the label to the position of the mouse cursor, but a bit higher if closestedge is not None: self.time_label.textNodePath.show() self.time_label.setPos(*(ray_aufpunkt + ray_direction * 1.)) # figure out the parameter t t = np.linalg.norm(closestedge.getTailPoint() - math_utils.np_to_p3d_Vec3(c2))/np.linalg.norm(closestedge.getTailPoint() - closestedge.getTipPoint()) # print("t = np.linalg.norm(closestedge.getTailPoint() - math_utils.np_to_p3d_Vec3(c2))/np.linalg.norm(closestedge.getTailPoint() - closestedge.getTipPoint())") # print(t, "np.linalg.norm(", closestedge.getTailPoint(), " - ", math_utils.np_to_p3d_Vec3(c2), ")/, np.linalg.norm(", closestedge.getTailPoint(), " - ", closestedge.getTipPoint(), ")") self.time_label.setText("t = {0:.2f}".format(t)) self.time_label.update() self.time_label.textNodePath.setScale(0.04) else: self.time_label.textNodePath.hide() # -- color edges if closestedge is not None: for edge in self.draggablegraph.graph_edges: # color all edge.setColor(Vec4(1., 1., 1., 1.), 1) if edge is closestedge: edge.setColor(Vec4(1., 0., 0., 1.), 1) else: # hide the connection line self.shortest_distance_line.hide() # make all the same color for edge in self.draggablegraph.graph_edges: edge.setColor(Vec4(1., 1., 1., 1.), 1) self.hoverindicatorpoint.setPos(math_utils.np_to_p3d_Vec3( ray_aufpunkt + ray_direction * 1.)) # -- color point # ---- find closest point, # within a certain radius (FIXME: automatically calculate that radius based on the # sorroundings) d_min_point = None closestpoint = None for point in self.draggablegraph.graph_points: d = np.linalg.norm(math_utils.p3d_to_np(point.getPos()) - math_utils.p3d_to_np(ray_aufpunkt)) if d_min_point is not None: if d < d_min_point: d_min_point = d closestpoint = point else: d_min_point = d closestpoint = point # ---- color in point for point in self.draggablegraph.graph_points: point.setColor(Vec4(1., 0., 1., 1.), 1) if point is closestpoint: point.setColor(Vec4(1., 0., 0., 1.), 1) else: point.setColor(Vec4(1., 1., 1., 1.), 1)
def render_hints(self): """ render various on-hover things: - cursors - time labels """ get_hover_points_success, ray_direction, ray_aufpunkt, edge_p1, edge_p2, c1, c2 = ( self.get_hover_points()) if get_hover_points_success is True: if math_utils.isPointBetweenTwoPoints(edge_p1, edge_p2, c1): self.shortest_distance_line.setTipPoint(math_utils.np_to_p3d_Vec3(c1)) self.shortest_distance_line.setTailPoint(math_utils.np_to_p3d_Vec3(c2)) self.shortest_distance_line.show() # -- set the time label # ---- set the position of the label to the position of the mouse cursor, # but a bit higher self.time_label.textNodePath.show() self.time_label.setPos(*(ray_aufpunkt + ray_direction * 1.)) a = self.get_a_param(c2) t = a * self.edge_graphics.get_duration_func() self.time_label.setText("t = {0:.2f}, a = {1:.2f}".format(t, a)) self.time_label.update() self.time_label.textNodePath.setScale(0.04) # -- color edges # on hover, change the color to be # darker than otherwise primary_color = self.edge_graphics.get_primary_color() darkening_factor = 0.5 new_rgb_v3 = np.array([ primary_color[0], primary_color[1], primary_color[2]]) * darkening_factor new_color = Vec4(new_rgb_v3[0], new_rgb_v3[1], new_rgb_v3[2], 1.) # when hovered-over self.edge_graphics.set_primary_color(new_color, change_logical_primary_color=False) else: self.shortest_distance_line.setColor(Vec4(1., 1., 1., 1.), 1) # when not hovered-over self.edge_graphics.set_primary_color(self.edge_graphics.get_primary_color()) self.shortest_distance_line.hide() self.time_label.textNodePath.hide() # -- color point # ---- find closest point, # within a certain radius d_min_point = None closestpoint = None playerline_limiting_positions = [self.edge_graphics.get_inset_v1(), self.edge_graphics.get_inset_v2()] for pos in playerline_limiting_positions: d = np.linalg.norm( math_utils.p3d_to_np(pos) - math_utils.p3d_to_np(ray_aufpunkt)) if d_min_point is not None: if d < d_min_point: d_min_point = d closestpoint = pos else: d_min_point = d closestpoint = pos
def draw_nbody_system(self): shade_of_gray = 0.1 base.setBackgroundColor(shade_of_gray, shade_of_gray, shade_of_gray) ob = OrbiterOrtho(base.cam, r_init=3.) # ob.set_view_to_xy_plane() # ob.set_view_to_xz_plane() cs = CoordinateSystem(ob) from plot_utils.nbodysystem.calc import get_pos_as_func_of_time animation_length_factor = 10. stop_time = 5. * animation_length_factor num_points = int(1000 * math.floor(animation_length_factor)) # make all bodies white nbodies_color = (1., 1., 1., 1.) d = 3 # two bodies: two points num_of_bodies = 5 def get_radius_from_mass_3d_sphere(mass): """ assume incompressibility Args: mass: a positive number Returns: radius """ rho = 1. return (3. * mass / (4. * rho * np.pi))**(1./3.) import plot_utils.colors.colors as colors ps = [] # graphics: points vs = [] # velocity vectors paths = [] # paths (tracing out movement) vis = [] xis = [] ms = [] ncs = [] cols = [] for n in range(num_of_bodies): vi = np.array([0.2 * np.random.rand(), 0.2 * np.random.rand(), 0.2 * np.random.rand()]) * (-1.)**math.floor(np.random.rand()*10) * 0.4 # consistent with d=3 xi = np.array([np.random.rand(), np.random.rand(), np.random.rand()]) * (-1.)**math.floor(np.random.rand()*10) * 0.65 vis.append(vi) xis.append(xi) # resolved error: nan's in result when mi and nc are n-dependent ... mi = (1. + n) * 5 ms.append(mi) nc = (-1.)**math.floor(np.random.rand()*10) ncs.append(nc) color = colors.get_next_mpl_color() cols.append(color) p = Point3d(scale=get_radius_from_mass_3d_sphere(mi)) p.setColor(color) p.setPos(math_utils.np_to_p3d_Vec3(xi)) ps.append(p) v = Vector() v.setColor(color) vs.append(v) paths.append(primitives.SegmentedLinePrimitive(color=Vec4(*color))) vis = [vi * 0.1 for vi in vis] def render_nbodysystem(a, tup, ps, vs, paths): """ Args: a: param between 0 and 1 -> time tup: tuple returned from solution function (t, vels, poss) ps: list of graphical points """ t = np.array(tup[0]) vels = tup[1] poss = tup[2] duration = max(t) assert duration == stop_time # display one out of the discrete calculated positions, the closest one to the time in the sequence i_to_display = np.where(t <= a * duration)[0][-1] # import ipdb; ipdb.set_trace() # noqa BREAKPOINT for n in range(num_of_bodies): # cut the vector down/extend the vector to a 3d vector, since you can't plot more or less than 3d # import ipdb; ipdb.set_trace() # noqa BREAKPOINT pos_of_particle_np = math_utils.get_3d_vec_from_nd_vec( poss[n][i_to_display]) pos_of_particle = math_utils.np_to_p3d_Vec3(pos_of_particle_np) vel_of_particle_np = math_utils.get_3d_vec_from_nd_vec( vels[n][i_to_display]) vel_of_particle = math_utils.np_to_p3d_Vec3(vel_of_particle_np) ps[n].setPos(pos_of_particle) # plot the velocity vectors vs[n].setTailPoint(pos_of_particle) vel_vector_to_plot = pos_of_particle + vel_of_particle if np.linalg.norm(vel_of_particle_np) >= 1: vel_vector_to_plot = math_utils.np_to_p3d_Vec3( pos_of_particle_np + math_utils.normalize(vel_of_particle_np) * np.log(np.linalg.norm(vel_of_particle_np))) vs[n].setTipPoint(vel_vector_to_plot) # trace out the paths over time paths[n].extendCoords([pos_of_particle_np]) pass myseq = Sequence(duration=stop_time, extraArgs=[ # the solution vector including the times get_pos_as_func_of_time( ms, ncs, vis, xis, stoptime=stop_time, numpoints=num_points, d=d, num_of_bodies=num_of_bodies), ps, vs, paths ], update_function=render_nbodysystem) myseq.start()
def update(self): """ resets the positions """ orbit_center = math_utils.np_to_p3d_Vec3( self.camera_gear.get_orbit_center()) if not self.l1o: self.l1o = Line1dSolid(thickness=self.crosshair_outer_thickness, color=self.crosshair_outer_color) self.l1o.reparentTo(self) self.l1o.set_render_above_all(True) self.l1o.setTailPoint(orbit_center - Vec3(self.crosshair_outer_lines_length / 2., 0., 0.)) self.l1o.setTipPoint(orbit_center + Vec3(self.crosshair_outer_lines_length / 2., 0., 0.)) if not self.l2o: self.l2o = Line1dSolid(thickness=self.crosshair_outer_thickness, color=self.crosshair_outer_color) self.l2o.reparentTo(self) self.l2o.set_render_above_all(True) self.l2o.setTailPoint(orbit_center - Vec3(0., self.crosshair_outer_lines_length / 2., 0.)) self.l2o.setTipPoint(orbit_center + Vec3(0., self.crosshair_outer_lines_length / 2., 0.)) if not self.l3o: self.l3o = Line1dSolid(thickness=self.crosshair_outer_thickness, color=self.crosshair_outer_color) self.l3o.reparentTo(self) self.l3o.set_render_above_all(True) self.l3o.setTailPoint(orbit_center - Vec3(0., 0., self.crosshair_outer_lines_length / 2.)) self.l3o.setTipPoint(orbit_center + Vec3(0., 0., self.crosshair_outer_lines_length / 2.)) if not self.l1i: self.l1i = Line1dSolid(thickness=self.crosshair_inner_thickness, color=self.crosshair_inner_color) self.l1i.set_render_above_all(True) self.l1i.reparentTo(self) self.l1i.setTailPoint(orbit_center - Vec3(self.crosshair_inner_lines_length / 2., 0., 0.)) self.l1i.setTipPoint(orbit_center + Vec3(self.crosshair_inner_lines_length / 2., 0., 0.)) if not self.l2i: self.l2i = Line1dSolid(thickness=self.crosshair_inner_thickness, color=self.crosshair_inner_color) self.l2i.set_render_above_all(True) self.l2i.reparentTo(self) self.l2i.setTailPoint(orbit_center - Vec3(0., self.crosshair_inner_lines_length / 2., 0.)) self.l2i.setTipPoint(orbit_center + Vec3(0., self.crosshair_inner_lines_length / 2., 0.)) if not self.l3i: self.l3i = Line1dSolid(thickness=self.crosshair_inner_thickness, color=self.crosshair_inner_color) self.l3i.set_render_above_all(True) self.l3i.reparentTo(self) self.l3i.setTailPoint(orbit_center - Vec3(0., 0., self.crosshair_inner_lines_length / 2.)) self.l3i.setTipPoint(orbit_center + Vec3(0., 0., self.crosshair_inner_lines_length / 2.))