Esempio n. 1
0
class OrbitPlotter3D(_PlotlyOrbitPlotter):
    """OrbitPlotter3D class."""
    def __init__(self, figure=None, dark=False, *, num_points=150, plane=None):
        super().__init__(figure, num_points=num_points, plane=plane)
        self._layout = Layout(
            autosize=True,
            scene=dict(
                xaxis=dict(title="x (km)"),
                yaxis=dict(title="y (km)"),
                zaxis=dict(title="z (km)"),
                aspectmode="data",  # Important!
            ),
        )
        if dark:
            self._layout.template = "plotly_dark"

    def _draw_point(self, radius, color, name, center=[0, 0, 0] * u.km):
        # We use _plot_sphere here because it's not easy to specify the size of a marker
        # in data units instead of pixels, see
        # https://stackoverflow.com/q/47086547
        return self._draw_sphere(radius, color, name, center)

    def _draw_sphere(self, radius, color, name, center=[0, 0, 0] * u.km):
        xx, yy, zz = generate_sphere(radius, center)
        sphere = Surface(
            x=xx.to(u.km).value,
            y=yy.to(u.km).value,
            z=zz.to(u.km).value,
            name=name,
            colorscale=[[0, color], [1, color]],
            cauto=False,
            cmin=1,
            cmax=1,
            showscale=False,
        )
        self._figure.add_trace(sphere)

        return sphere

    def _plot_coordinates(self, coordinates, label, colors, dashed):
        trace = Scatter3d(
            x=coordinates.x.to(u.km).value,
            y=coordinates.y.to(u.km).value,
            z=coordinates.z.to(u.km).value,
            name=label,
            line=dict(color=colors[0],
                      width=5,
                      dash="dash" if dashed else "solid"),
            mode="lines",  # Boilerplate
        )
        self._figure.add_trace(trace)

        return trace, [trace.line.color]

    def plot(self, orbit, *, label=None, color=None, trail=False):
        """Plots state and osculating orbit in their plane.

        Parameters
        ----------
        orbit : ~poliastro.twobody.orbit.Orbit
            Orbit to plot.
        label : string, optional
            Label of the orbit.
        color : string, optional
            Color of the line and the position.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """
        if trail:
            raise NotImplementedError("trail not supported yet")

        return super().plot(orbit, label=label, color=color, trail=trail)

    @u.quantity_input(elev=u.rad, azim=u.rad, distance=u.km)
    def set_view(self, elev, azim, distance=5 * u.km):
        """Changes 3D view."""
        x = distance * np.cos(elev) * np.cos(azim)
        y = distance * np.cos(elev) * np.sin(azim)
        z = distance * np.sin(elev)

        self._layout.update({
            "scene": {
                "camera": {
                    "eye": {
                        "x": x.to(u.km).value,
                        "y": y.to(u.km).value,
                        "z": z.to(u.km).value,
                    }
                }
            }
        })

        if not self._figure._in_batch_mode:
            return self.show()
Esempio n. 2
0
class OrbitPlotter3D(BaseOrbitPlotter):
    """OrbitPlotter3D class.

    """
    def __init__(self, figure=None, dark=False):
        super().__init__(figure)
        self._layout = Layout(
            autosize=True,
            scene=dict(
                xaxis=dict(title="x (km)"),
                yaxis=dict(title="y (km)"),
                zaxis=dict(title="z (km)"),
                aspectmode="data",  # Important!
            ),
        )
        if dark:
            self._layout.template = "plotly_dark"

    def _plot_point(self, radius, color, name, center=[0, 0, 0] * u.km):
        # We use _plot_sphere here because it's not easy to specify the size of a marker
        # in data units instead of pixels, see
        # https://stackoverflow.com/q/47086547
        return self._plot_sphere(radius, color, name, center)

    def _plot_sphere(self, radius, color, name, center=[0, 0, 0] * u.km):
        xx, yy, zz = generate_sphere(radius, center)
        sphere = Surface(
            x=xx.to(u.km).value,
            y=yy.to(u.km).value,
            z=zz.to(u.km).value,
            name=name,
            colorscale=[[0, color], [1, color]],
            cauto=False,
            cmin=1,
            cmax=1,
            showscale=False,
        )
        self._figure.add_trace(sphere)

        return sphere

    def _plot_trajectory(self, trajectory, label, color, dashed):
        trace = Scatter3d(
            x=trajectory.x.to(u.km).value,
            y=trajectory.y.to(u.km).value,
            z=trajectory.z.to(u.km).value,
            name=label,
            line=dict(color=color, width=5,
                      dash="dash" if dashed else "solid"),
            mode="lines",  # Boilerplate
        )
        self._figure.add_trace(trace)

        return trace

    @u.quantity_input(elev=u.rad, azim=u.rad, distance=u.km)
    def set_view(self, elev, azim, distance=5 * u.km):
        x = distance * np.cos(elev) * np.cos(azim)
        y = distance * np.cos(elev) * np.sin(azim)
        z = distance * np.sin(elev)

        self._layout.update({
            "scene": {
                "camera": {
                    "eye": {
                        "x": x.to(u.km).value,
                        "y": y.to(u.km).value,
                        "z": z.to(u.km).value,
                    }
                }
            }
        })

        if not self._figure._in_batch_mode:
            return self.show()