Пример #1
0
"""Interpolate the arrays of a source Mesh (RandomHills)
onto another (ellipsoid) by averaging closest point values"""
from vedo import ParametricShape, Sphere, show

# RandomHills already contains the height as a scalar defined on vertices
h = ParametricShape('RandomHills')
h.cmap('hsv', vmin=0, vmax=6)
h.addScalarBar3D(title='RandomHills height scalar value')

# interpolate such values on a completely different Mesh.
# pick N=4 closest points and assign an ave value based on shepard kernel.
s = Sphere().scale([1, 1, 0.5]).pos(-.1, 1.5, 0.3).alpha(1).lw(0.1)
s.interpolateDataFrom(h, N=4, kernel='gaussian')
s.cmap('hsv', vmin=0, vmax=6)

show(h, s, __doc__, axes=1)
Пример #2
0
        data.append([place, theta, phi, confirmed, deaths, recos])
    data.append(['U.S.A.\n', 0.9, 1.4, conf_us, deat_us, reco_us])
    return (date, data, csvdata['Confirmed'].sum(), csvdata['Deaths'].sum(),
            csvdata['Recovered'].sum())


# Create the scene -------------------------------------------------------------
from vedo import spher2cart, Sphere, Text2D, Earth, merge, show

date, data, allconf, alldeat, allreco = load_data()
s1, s2, vigs = [], [], []
for place, theta, phi, confirmed, deaths, recos in data:
    pos = spher2cart(1, theta, phi)
    fl = 'cases: ' + str(confirmed) + '\ndeaths: ' + str(deaths)
    radius = np.power(confirmed, 1 / 3) / 4000
    sph1 = Sphere(pos, radius, alpha=0.4, res=12).flag(place + fl)
    if deaths > 20000:
        sph1.flag(fl)
        anchorpt = sph1.pos() * (1 + radius)
        vig = sph1.vignette(place, anchorpt, font="Kanopus")
        vig.c('k').scale(1.5 * (1 + radius)).followCamera()
        vigs.append(vig)
    s1.append(sph1)
    s2.append(
        Sphere(pos, np.power(deaths, 1 / 3) / 10000, alpha=0.4, c='k', res=10))

tx = Text2D('COVID-19 spread on ' + date + '\n# cases : ' + str(allconf) +
            '\n# deaths: ' + str(alldeat) + '\n# recovd: ' + str(allreco) +
            '\n(hover mouse for local info)',
            font="VictorMono")
Пример #3
0
    pts = []
    for i, longs in enumerate(agrid_reco):
        ilat = grid_reco.lats()[i]
        for j, value in enumerate(longs):
            ilong = grid_reco.lons()[j]
            th = np.deg2rad(90 - ilat)
            ph = np.deg2rad(ilong)
            r = value + rbias
            p = np.array([sin(th) * cos(ph), sin(th) * sin(ph), cos(th)]) * r
            pts.append(p)
    return pts


vp = Plotter(shape=[2, 2], axes=3, interactive=0)

shape1 = Sphere(alpha=0.2)
shape2 = vp.load(datadir + "icosahedron.vtk").normalize().lineWidth(1)

agrid1, actorpts1 = makeGrid(shape1, N)

vp.show(shape1, actorpts1, at=0)

agrid2, actorpts2 = makeGrid(shape2, N)
vp.show(shape2, actorpts2, at=1)

vp.camera.Zoom(1.2)
vp.interactive = False

clm1 = pyshtools.SHGrid.from_array(agrid1).expand()
clm2 = pyshtools.SHGrid.from_array(agrid2).expand()
# clm1.plot_spectrum2d()  # plot the value of the sph harm. coefficients
Пример #4
0
def make_actor_label(
    atlas,
    actors,
    labels,
    size=300,
    color=None,
    radius=100,
    xoffset=0,
    yoffset=-500,
    zoffset=0,
):
    """
    Adds a 2D text ancored to a point on the actor's mesh
    to label what the actor is

    :param kwargs: key word arguments can be passed to determine
            text appearance and location:
                - size: int, text size. Default 300
                - color: str, text color. A list of colors can be passed
                        if None the actor's color is used. Default None.
                - xoffset, yoffset, zoffset: integers that shift the label position
                - radius: radius of sphere used to denote label anchor. Set to 0 or None to hide.
    """
    offset = [-yoffset, -zoffset, xoffset]
    default_offset = np.array([0, -200, 100])

    new_actors = []
    for n, (actor, label) in enumerate(zip(listify(actors), listify(labels))):

        # Get label color
        if color is None:
            color = [0.2, 0.2, 0.2]

        # Get mesh's highest point
        points = actor.points().copy()
        point = points[np.argmin(points[:, 1]), :]
        point += np.array(offset) + default_offset

        try:
            if atlas.hemisphere_from_coords(point, as_string=True) == "left":
                point = atlas.mirror_point_across_hemispheres(point)
        except IndexError:
            pass

        # Create label
        txt = Text3D(label, point, s=size, c=color)
        txt._kwargs = dict(
            size=size,
            color=color,
            radius=radius,
            xoffset=xoffset,
            yoffset=yoffset,
            zoffset=zoffset,
        )

        # rotate label
        p = txt.pos()
        txt.pos(x=0, y=0, z=0).rotateX(180).rotateY(180).pos(p)

        new_actors.append(txt)

        # Mark a point on Mesh that corresponds to the label location
        if radius is not None:
            pt = actor.closestPoint(point)
            sphere = Sphere(pt, r=radius, c=color)
            sphere.ancor = pt
            new_actors.append(sphere)

    return new_actors
Пример #5
0
from vedo import Cone, Sphere, merge, Volume
import numpy as np
import vtk

print('---------------------------------')
print('vtkVersion', vtk.vtkVersion().GetVTKVersion())
print('---------------------------------')

#####################################
cone = Cone(res=48)
sphere = Sphere(res=24)

carr = cone.cellCenters()[:, 2]
parr = cone.points()[:, 0]

cone.pointdata["parr"] = parr
cone.celldata["carr"] = carr

carr = sphere.cellCenters()[:, 2]
parr = sphere.points()[:, 0]

sphere.pointdata["parr"] = parr
sphere.celldata["carr"] = carr

sphere.pointdata["pvectors"] = np.sin(sphere.points())

sphere.addElevationScalars()

cone.computeNormals()
sphere.computeNormals()
Пример #6
0
    ListPos.append(PossiblePos[n])
    del PossiblePos[n]
Pos = np.array(ListPos)

# Create an array with all the radius and a list with all the masses
Radius = np.concatenate((np.array([Rb]), np.array([Rs] * (Nsp - 1))))
Mass = [1.0] + [Ms] * (Nsp - 1)

# Create the initial array of velocities at random with big sphere at rest
ListVel = [(0.0, 0.0)]
for s in range(1, Nsp):
    ListVel.append((Rb * random.uniform(-1, 1), Rb * random.uniform(-1, 1)))
Vel = np.array(ListVel)

# Create the spheres
Spheres = [Sphere(pos=(Pos[0][0], Pos[0][1], 0), r=Radius[0], c="red", res=12).phong()]
for s in range(1, Nsp):
    a = Sphere(pos=(Pos[s][0], Pos[s][1], 0), r=Radius[s], c="blue", res=6).phong()
    Spheres.append(a)
#    plt += a
plt += Spheres
plt += Grid(sx=screen_w, sy=screen_w)

# Auxiliary variables
Id = np.identity(Nsp)
Dij = (Radius + Radius[:, np.newaxis]) ** 2  # Matrix Dij=(Ri+Rj)**2

# The main loop
pb = ProgressBar(0, 2000, c="r")
for i in pb.range():
    # Update all positions
Пример #7
0
# Create the initial positions and velocitites (0,0) of the bobs
bob_x = [0]
bob_y = [0]
x_dot = np.zeros(N+1)  # velocities
y_dot = np.zeros(N+1)

for k in range(1, N + 1):
    alpha = np.pi / 5 * k / 10
    bob_x.append(bob_x[k - 1] + np.cos(alpha) + np.random.normal(0, 0.1))
    bob_y.append(bob_y[k - 1] + np.sin(alpha) + np.random.normal(0, 0.1))

# Create the bobs
vp = Plotter(title="Multiple Pendulum", axes=0, interactive=0, bg2='ly')
vp += Box(pos=(0, -5, 0), length=12, width=12, height=0.7, c="k").wireframe(1)
bob = [vp.add(Sphere(pos=(bob_x[0], bob_y[0], 0), r=R / 2, c="gray"))]
for k in range(1, N + 1):
    c = Cylinder(pos=(bob_x[k], bob_y[k], 0), r=R, height=0.3, c=k)
    vp += c
    bob.append(c)

# Create the springs out of N links
link = [None] * N
for k in range(N):
    p0 = bob[k].pos()
    p1 = bob[k + 1].pos()
    link[k] = Spring(p0, p1, thickness=0.015, r=R / 3, c="gray")
    vp += link[k]

# Create some auxiliary variables
x_dot_m = np.zeros(N+1)
Пример #8
0
"""Build a custom colormap, including
out-of-range and NaN colors and labels"""
from vedo import buildLUT, Sphere, show, settings

settings.useDepthPeeling = True  # might help with transparencies

# generate a sphere and stretch it, so it sits between z=-2 and z=+2
mesh = Sphere(quads=True).scale([1, 1, 2]).lineWidth(0.1)

# create some dummy data array to be associated to points
data = mesh.points()[:, 2]  # pick z-coords, use them as scalar data
data[10:70] = float('nan')  # make some values invalid by setting to NaN
data[300:600] = 100  # send some values very far above-scale

# build a custom LookUp Table of colors:
#               value, color, alpha
lut = buildLUT(
    [
        #(-2, 'pink'      ),  # up to -2 is pink
        (0.0, 'pink'),  # up to 0 is pink
        (0.4, 'green', 0.5),  # up to 0.4 is green with alpha=0.5
        (0.7, 'darkblue'),
        #( 2, 'darkblue'  ),
    ],
    vmin=-1.2,
    belowColor='lightblue',
    vmax=0.7,
    aboveColor='grey',
    nanColor='red',
    interpolate=False,
)
Пример #9
0
def make_actor_label(
    atlas,
    actors,
    labels,
    size=300,
    color=None,
    radius=100,
    xoffset=0,
    yoffset=0,
    zoffset=0,
):
    """
        Adds a 2D text ancored to a point on the actor's mesh
        to label what the actor is

        :param kwargs: key word arguments can be passed to determine 
                text appearance and location:
                    - size: int, text size. Default 300
                    - color: str, text color. A list of colors can be passed
                            if None the actor's color is used. Default None.
                    - xoffset, yoffset, zoffset: integers that shift the label position
                    - radius: radius of sphere used to denote label anchor. Set to 0 or None to hide. 
    """
    # Check args
    if not isinstance(actors, (tuple, list)):
        actors = [actors]
    if not isinstance(labels, (tuple, list)):
        labels = [labels]

    if atlas.atlas_name == "ABA":
        offset = [-yoffset, -zoffset, xoffset]
        default_offset = np.array([0, -200, 100])
    else:
        offset = [xoffset, yoffset, zoffset]
        default_offset = np.array([100, 0, -200])

    new_actors = []
    for n, (actor, label) in enumerate(zip(actors, labels)):
        if not isinstance(actor, Mesh):
            raise ValueError(
                f"Mesh must be an instance of Mesh, not {type(actor)}")
        if not isinstance(label, str):
            raise ValueError(f"Label must be a string, not {type(label)}")

        # Get label color
        if color is None:
            color = actor.c()
        elif isinstance(color, (list, tuple)):
            color = color[n]

        # Get mesh's highest point
        points = actor.points().copy()
        point = points[np.argmin(points[:, 1]), :]
        point += np.array(offset) + default_offset

        try:
            if atlas.hemisphere_from_coords(point, as_string=True) == "left":
                point = atlas.mirror_point_across_hemispheres(point)
        except IndexError:
            pass

        # Create label
        txt = Text(label, point, s=size, c=color)
        txt._original_actor = actor
        txt._label = label
        txt._kwargs = dict(
            size=size,
            color=color,
            radius=radius,
            xoffset=xoffset,
            yoffset=yoffset,
            zoffset=zoffset,
        )

        new_actors.append(txt)

        # Mark a point on Mesh that corresponds to the label location
        if radius is not None:
            pt = actor.closestPoint(point)
            sphere = Sphere(pt, r=radius, c=color)
            sphere.ancor = pt
            new_actors.append(sphere)

    return new_actors
Пример #10
0
"""Simulation of an optical system with lenses and mirrors of arbitrary shapes and orientations
(points mark the exit locations of photons, many from total internal reflections)"""
from vedo import Grid, Sphere, Cube, Cone, Points, show
from optics_base import Lens, Ray, Mirror, Screen  # see file ./optics_base.py
import numpy as np

# Create meshes as ordinary vedo objects
sm = Sphere(r=8).z(-8.1)
sp = Sphere(r=8).z(+8.1)
shape1 = Sphere(r=0.9, res=53).cutWithPlane().cap().rotateY(-90).pos(0, 0, 0.5)
shape2 = Cube(side=2).triangulate().boolean('-', sm).boolean("-", sp).z(3)
shape3 = Cone().rotateY(-90).z(6)
shape4 = Cube().scale([1.7, 1, 0.2]).rotateY(70).pos(-0.3, 0, 8)
shape5 = Sphere(r=2).boolean("intersect",
                             Sphere(r=2).z(3.5)).rotateX(10).pos(0.8, 0, 7.5)
shape6 = Grid(resx=1, resy=1).rotateY(-60).rotateX(30).pos(0, -1, 11)

# Build lenses (with their refractive indices), and mirrors, using those meshes
lens1 = Lens(shape1, ref_index=1.35).c("blue9")  # constant refr. index
lens2 = Lens(shape2, ref_index="glass").c("blue7")
lens3 = Lens(shape3, ref_index="glass").c("green9")
lens4 = Lens(shape4, ref_index="glass").c("purple9").lineWidth(1)
lens5 = Lens(shape5, ref_index="glass").c("orange9")
mirror = Mirror(shape6)
screen = Screen(4, 4).rotateY(20).pos(1, 0, 12)
elements = [lens1, lens2, lens3, lens4, lens5, mirror, screen]

# Generate photons and trace them through the optical elements
lines = []
source = Grid(resx=20, resy=20).points()  # a numpy array
for pt in source:
Пример #11
0
"""Non blocking interactive rendering window,
python flow is not blocked
but displayed objects cannot be accessed"""
import time, os
from multiprocessing import Process
from vedo import Sphere, show, printc

printc("..starting main", c='g')

sphere = Sphere().alpha(0.1).lw(0.1)

# ------ instead of (typical):
#show(sphere, __doc__, axes=1)


# ------ spawn an independent subprocess:
def spawn():
    show(sphere, __doc__, axes=1)


Process(target=spawn).start()

printc("..python flow is not blocked, wait 1 sec..", c='y')
time.sleep(1)

printc("..continuing in main", c='r')
os._exit(0)  # this exits immediately with no cleanup or buffer flushing
Пример #12
0
"""Click a sphere to highlight it"""
from vedo import Text2D, Sphere, Plotter
import numpy as np

spheres = []
for i in range(25):
    p = np.random.rand(2)
    s = Sphere(r=0.05).pos(p).color('k5')
    s.name = f"sphere nr.{i} at {p}"
    spheres.append(s)

def func(evt):
    if not evt.actor: return
    sil = evt.actor.silhouette().lineWidth(6).c('red5')
    msg.text("You clicked: "+evt.actor.name)
    plt.remove(silcont.pop()).add(sil)
    silcont.append(sil)

silcont = [None]
msg = Text2D("", pos="bottom-center", c='k', bg='r9', alpha=0.8)

plt = Plotter(axes=1, bg='black')
plt.addCallback('mouse click', func)
plt.show(spheres, msg, __doc__, zoom=1.2)
Пример #13
0
    ListPos.append(PossiblePos[n])
    del PossiblePos[n]
Pos = np.array(ListPos)

# Create an array with all the radius and a list with all the masses
Radius = np.concatenate((np.array([Rb]), np.array([Rs] * (Nsp - 1))))
Mass = [1.0] + [Ms] * (Nsp - 1)

# Create the initial array of velocities at random with big sphere at rest
ListVel = [(0.0, 0.0)]
for s in range(1, Nsp):
    ListVel.append((Rb * random.uniform(-1, 1), Rb * random.uniform(-1, 1)))
Vel = np.array(ListVel)

# Create the spheres
Spheres = [Sphere(pos=(Pos[0][0], Pos[0][1], 0), r=Radius[0], c="red")]
for s in range(1, Nsp):
    a = Sphere(pos=(Pos[s][0], Pos[s][1], 0), r=Radius[s], c="blue")
    Spheres.append(a)
#    vp += a
vp += Spheres
vp += Grid(sx=screen_w, sy=screen_w)

# Auxiliary variables
Id = np.identity(Nsp)
Dij = (Radius + Radius[:, np.newaxis])**2  # Matrix Dij=(Ri+Rj)**2

# The main loop
pb = ProgressBar(0, 2000, c="r")
for i in pb.range():
    # Update all positions
Пример #14
0
"""Customizing Axes.
Cartesian planes can be displaced
from their lower-range default position"""
from vedo import Sphere, Axes, precision, show, settings

# settings.useDepthPeeling = True

sph = Sphere().scale([4, 3, 2]).shift(5, 6, 7).c('green2', 0.1)

axs = Axes(
    sph,  # build axes for object sph
    xtitle="x axis",
    ytitle="y axis",
    ztitle="z axis",
    htitle='An ellipsoid at ' + precision(sph.centerOfMass(), 2),
    hTitleFont=1,
    hTitleColor='red3',
    zxGrid=True,
    xyFrameLine=2,
    yzFrameLine=2,
    zxFrameLine=2,
    xyFrameColor='red3',
    yzFrameColor='green3',
    zxFrameColor='blue3',
    xyShift=0.2,  # move xy plane 20% along z
    yzShift=0.2,  # move yz plane 20% along x
    zxShift=0.2,  # move zx plane 20% along y
)

show(sph, axs, __doc__).close()
Пример #15
0
# Create the initial positions and velocitites (0,0) of the bobs
bob_x = [0]
bob_y = [0]
x_dot = np.zeros(N + 1)  # velocities
y_dot = np.zeros(N + 1)

for k in range(1, N + 1):
    alpha = np.pi / 5 * k / 10
    bob_x.append(bob_x[k - 1] + np.cos(alpha) + np.random.normal(0, 0.1))
    bob_y.append(bob_y[k - 1] + np.sin(alpha) + np.random.normal(0, 0.1))

# Create the bobs
vp = Plotter(title="Multiple Pendulum", axes=0, interactive=0, bg2='ly')
vp += Box(pos=(0, -5, 0), length=12, width=12, height=0.7, c="k").wireframe(1)
sph = Sphere(pos=(bob_x[0], bob_y[0], 0), r=R / 2, c="gray")
vp += sph
bob = [sph]
for k in range(1, N + 1):
    c = Cylinder(pos=(bob_x[k], bob_y[k], 0), r=R, height=0.3, c=k)
    vp += c
    bob.append(c)

# Create the springs out of N links
link = [None] * N
for k in range(N):
    p0 = bob[k].pos()
    p1 = bob[k + 1].pos()
    link[k] = Spring(p0, p1, thickness=0.015, r=R / 3, c="gray")
    vp += link[k]
Пример #16
0
"""Compute the (signed) distance of one mesh to another"""
from vedo import Sphere, Cube, show

s1 = Sphere().x(10)
s2 = Cube(c='grey4').scale([2, 1, 1]).x(14)

s1.distanceTo(s2, signed=False)
s1.cmap('hot').addScalarBar('Signed\nDistance')
# print(s1.pointdata["Distance"])  # numpy array

show(s1, s2, __doc__, axes=1, size=(1000, 500), zoom=1.5).close()
Пример #17
0
plt += __doc__
plt += Torus(c="g", r=RingRadius, thickness=RingThickness, alpha=0.1).wireframe(1)  ### <--

Atoms = []
poslist = []
plist, mlist, rlist = [], [], []
mass = Matom * Ratom ** 3 / Ratom ** 3
pavg = np.sqrt(2.0 * mass * 1.5 * k * T)  # average kinetic energy p**2/(2mass) = (3/2)kT

for i in range(Natoms):
    alpha = 2 * np.pi * random()
    x = RingRadius * np.cos(alpha) * 0.9
    y = RingRadius * np.sin(alpha) * 0.9
    z = 0
    atm = Sphere(pos=(x, y, z), r=Ratom, c=i, res=6).phong()
    plt += atm
    Atoms = Atoms + [atm]  ### <--
    theta = np.pi * random()
    phi = 2 * np.pi * random()
    px = pavg * np.sin(theta) * np.cos(phi)
    py = pavg * np.sin(theta) * np.sin(phi)
    pz = pavg * np.cos(theta)
    poslist.append((x, y, z))
    plist.append((px, py, pz))
    mlist.append(mass)
    rlist.append(Ratom)

pos = np.array(poslist)
poscircle = pos
p = np.array(plist)
Пример #18
0
"""
Example usage of addTrail().
Add a trailing line to a moving object.
"""
print(__doc__)
from vedo import Plotter, sin, Sphere, Point

plt = Plotter(axes=6, interactive=False)

s = Sphere().c("green").bc("tomato")
s.cutWithPlane([-0.9, 0, 0])  # cut left part of sphere

p = Point([1, 1, 1], r=12, c="black")

# add a trail to point p with max length 0.5 and 50 segments
p.addTrail(lw=3, maxlength=0.5, n=50)

# add meshes to Plotter list
plt += [s, p]

for i in range(200):
    p.pos(-2 + i / 100.0, sin(i / 5.0) / 15, 0)
    plt.camera.Azimuth(-0.2)
    plt.show()
    if plt.escaped: break  # if ESC is hit during the loop

plt.close()
Пример #19
0
"""Computes the signed distance
from one mesh to another.
"""
from vedo import Sphere, Cube, show

s1 = Sphere()
s2 = Cube(pos=[1, 0, 0], c='white', alpha=0.4)

s1.distanceToMesh(s2, signed=True, negate=False)

s1.addScalarBar(title='Signed\nDistance')

#print(s1.getPointArray("Distance"))

show(s1, s2, __doc__)
Пример #20
0
def plot(
    data,
    names=None,
    colors=None,
    lines=None,
    targets=None,
    arrows=None,
    text=None,
    boxes=None,
    points=None,
    interactive=True,
):
    """
    A vedo wrapper for quicly visualizing well trajectories for QAQC purposes.

    Parameters
    ----------
        data: a trimesh.Trimesh object or a list of trimesh.Trimesh
        objects or a trmiesh.scene object
        names: list of strings (default: None)
            A list of names, index aligned to the list of well meshes.
        colors: list of strings (default: None)
            A list of color or colors. If a single color is listed then this is
            applied to all meshes in data, otherwise the list of colors is
            indexed to the list of meshes.
    """
    if isinstance(data, trimesh.scene.scene.Scene):
        meshes = [v for k, v in data.geometry.items()]
        if names is None:
            names = list(data.geometry.keys())

    # handle a single mesh being passed
    elif isinstance(data, trimesh.Trimesh):
        meshes = [data]

    else:
        meshes = data
        if names is not None:
            assert len(names) == len(data), \
                "Names must be length of meshes list else None"
    if colors is not None:
        if len(colors) == 1:
            colors = colors * len(names)
        else:
            assert len(colors) == len(names), \
                "Colors must be length of meshes list, 1 else None"

    if points is not None:
        points = [Sphere(p, r=30, c='grey') for p in points]

    meshes_vedo = []
    for i, mesh in enumerate(meshes):
        if i == 0:
            vertices = np.array(mesh.vertices)
            start_locations = np.array([mesh.vertices[0]])
        else:
            vertices = np.concatenate((vertices, np.array(mesh.vertices)),
                                      axis=0)
            start_locations = np.concatenate(
                (start_locations, np.array([mesh.vertices[0]])), axis=0)

        # convert to vedo mesh
        m_vedo = trimesh2vedo(mesh)
        if colors is not None:
            m_vedo.c(colors[i])
        if names is not None:
            m_vedo.flag(names[i])
        meshes_vedo.append(m_vedo)

    w = get_bb(vertices)

    axes = get_axes(w.world)

    # try and figure out a nice start camera position
    pos = w.bb_center
    vec1 = pos - [w.length, w.width, 0]
    vec2 = np.array([vec1[1], vec1[0], 0])
    pos_new = [pos[0], pos[1], -4000] + vec2 * 3
    camera_opts = dict(pos=pos_new, focalPoint=pos, viewup=[0., 0., -1.])

    show(meshes_vedo,
         w.world,
         lines,
         targets,
         arrows,
         boxes,
         axes,
         points,
         bg='lightgrey',
         bg2='lavender',
         camera=camera_opts,
         interactorStyle=10,
         resetcam=True,
         interactive=True,
         verbose=True,
         title=f'welleng {VERSION}')
Пример #21
0
"""Click a sphere to highlight it"""
from vedo import Sphere, Plotter
import numpy as np

pts = np.random.rand(30, 2) * 20
spheres = [Sphere().pos(p).color('k5') for p in pts]


def func(evt):
    if not evt.actor: return
    sil = evt.actor.silhouette().lineWidth(6).c('red5')
    plt.remove(silcont.pop()).add(sil)
    silcont.append(sil)


silcont = [None]
plt = Plotter(axes=1, bg='black')
plt.addCallback('mouse click', func)
plt.show(spheres, __doc__, zoom=1.2)