points1.append(Point(-7, 2, 2))
points1.append(Point(-6, 3, 1))
points1.append(Point(-4, 3, -1))
points1.append(Point(-3, 5, -2))
spline1 = BSplineCurve.from_points(points1)

points2 = []
points2.append(Point(-4, 0, 2))
points2.append(Point(-2, 2, 0))
points2.append(Point(2, 3, -1))
points2.append(Point(3, 7, -2))
points2.append(Point(4, 9, -1))
spline2 = BSplineCurve.from_points(points2)

surface = BSplineSurface.from_fill(spline1, spline2)

points = Collection(surface.xyz(nu=100, nv=100))

# ==============================================================================
# Viz
# ==============================================================================

mesh = surface.to_vizmesh()
boundary = Polyline(
    mesh.vertices_attributes('xyz', keys=mesh.vertices_on_boundary()))

view = App()
view.add(boundary, linewidth=2)
view.add(points, color=(1, 0, 0), size=30)
view.run()
from math import radians

from compas.geometry import Pointcloud, Box
from compas.geometry import Rotation
from compas.geometry import oriented_bounding_box_numpy

from compas_view2.app import App

cloud = Pointcloud.from_bounds(10, 5, 3, 100)

Rz = Rotation.from_axis_and_angle([0.0, 0.0, 1.0], radians(60))
Ry = Rotation.from_axis_and_angle([0.0, 1.0, 0.0], radians(20))
Rx = Rotation.from_axis_and_angle([1.0, 0.0, 0.0], radians(10))

cloud.transform(Rz * Ry * Rx)

bbox = oriented_bounding_box_numpy(cloud)
box = Box.from_bounding_box(bbox)

viewer = App()
viewer.add(cloud)
viewer.add(box, show_faces=False, linecolor=(1, 0, 0), linewidth=3)
viewer.run()
Exemple #3
0
front = Plane([0, -1, 0], [0, -1, 0])
back = Plane([0, +1, 0], [0, +1, 0])

halfspaces = array(
    [left.abcd, right.abcd, top.abcd, bottom.abcd, front.abcd, back.abcd],
    dtype=float)

interior = array([0, 0, 0], dtype=float)

hsi = HalfspaceIntersection(halfspaces, interior)
hull = ConvexHull(hsi.intersections)

mesh = Mesh.from_vertices_and_faces(
    [hsi.intersections[i] for i in hull.vertices], hull.simplices)
mesh.unify_cycles()

to_merge = []
for a, b in combinations(mesh.faces(), 2):
    na = Vector(*mesh.face_normal(a))
    nb = Vector(*mesh.face_normal(b))
    if na.dot(nb) >= 1:
        if na.cross(nb).length < 1e-6:
            to_merge.append([a, b])

for faces in to_merge:
    mesh.merge_faces(faces)

viewer = App()
viewer.add(mesh, show_vertices=True, pointsize=10)
viewer.run()
Exemple #4
0
# ==============================================================================
# Tesselation
# ==============================================================================

tess = ShapeTesselator(shell)
tess.Compute()

vertices = []
triangles = []

for i in range(tess.ObjGetVertexCount()):
    xyz = tess.GetVertex(i)
    vertices.append(xyz)

for i in range(tess.ObjGetTriangleCount()):
    a, b, c = tess.GetTriangleIndex(i)
    triangles.append([a, b, c])

mesh = Mesh.from_vertices_and_faces(vertices, triangles)

# ==============================================================================
# Viz
# ==============================================================================

print(mesh.number_of_vertices())
print(mesh.number_of_faces())

viewer = App()
viewer.add(mesh)
viewer.run()
Exemple #5
0
T = Translation.from_vector([0, -1.5, 0])
R = Rotation.from_axis_and_angle([0, 0, 1], radians(45))

surface.transform(R * T)

# ==============================================================================
# AABB
# ==============================================================================

box = surface.aabb()

# ==============================================================================
# Visualisation
# ==============================================================================

view = App()

for row in surface.points:
    view.add(Polyline(row),
             show_points=True,
             pointsize=20,
             pointcolor=(1, 0, 0),
             linewidth=2,
             linecolor=(1.0, 0, 0))

for col in zip(*surface.points):
    view.add(Polyline(col), linewidth=2, linecolor=(0, 1.0, 0))

view.add(surface.to_mesh(), show_edges=False)
view.add(box, show_faces=False)
c3.edges_attribute('crease', 3, keys=list(cage.face_halfedges(bottom)))

c4.edges_attribute('crease', 4, keys=list(cage.face_halfedges(top)))
c4.edges_attribute('crease', 4, keys=list(cage.face_halfedges(bottom)))

c5.edges_attribute('crease', 5, keys=list(cage.face_halfedges(top)))
c5.edges_attribute('crease', 5, keys=list(cage.face_halfedges(bottom)))

s0 = c0.subdivide(k=5)
s1 = c1.subdivide(k=5)
s2 = c2.subdivide(k=5)
s3 = c3.subdivide(k=5)
s4 = c4.subdivide(k=5)
s5 = c5.subdivide(k=5)

viewer = App()

viewer.add(c0, show_faces=False, show_edges=True)
viewer.add(s0)

viewer.add(c1, show_faces=False, show_edges=True)
viewer.add(s1)

viewer.add(c2, show_faces=False, show_edges=True)
viewer.add(s2)

viewer.add(c3, show_faces=False, show_edges=True)
viewer.add(s3)

viewer.add(c4, show_faces=False, show_edges=True)
viewer.add(s4)
from compas.geometry import Point
from compas.geometry import Polyline, Bezier
from compas_occ.geometry import OCCNurbsCurve
from compas_view2.app import App
from compas_view2.objects import Collection


points = [Point(0, 0, 0), Point(3, 6, 0), Point(6, -3, 3), Point(10, 0, 0)]
bezier = Bezier(points)
points = bezier.locus(10)

curve = OCCNurbsCurve.from_interpolation(points)

# ==============================================================================
# Visualisation
# ==============================================================================

view = App()

view.add(Polyline(curve.locus()), linewidth=3)
view.add(Collection(points))

view.run()
Exemple #8
0
from math import pi, cos, sin
from compas.utilities import pairwise
from compas.datastructures import Mesh
from compas_kagome.kagome import Kagome

from compas_view2.app import App
from compas.geometry import Point

# Kagome pattern for a simple patch with one singularity...
n = 5
vertices = [[cos(i / n * 2 * pi),
             sin(i / n * 2 * pi), 0.0] for i in range(n)] + [[0.0, 0.0, 0.0]]
faces = [[i, j, n] for i, j in pairwise(list(range(n)) + [0])]
coarse_tri_mesh = Mesh.from_vertices_and_faces(
    vertices, faces)  # hard-coded coarse triangulated mesh

# ...or Kagome pattern from a polyhedron
# coarse_tri_mesh = Mesh.from_polyhedron(20) # 4 or 20 for tetrahedron (4 faces) and icosahedron (20 faces)

kagome_mesh = Kagome.from_mesh(coarse_tri_mesh,
                               k=3)  # play with density value k

viewer = App()
for fkey in kagome_mesh.singularities():
    viewer.add(Point(*kagome_mesh.face_centroid(fkey)))
mesh = Mesh.from_vertices_and_faces(*kagome_mesh.to_vertices_and_faces())
viewer.add(mesh, show_edges=True)
viewer.run()
Exemple #9
0
        index1, index2, index3 = trian.Get()
        # for j in range(1, 4):
        #     if j == 1:
        #         m = index1
        #         n = index2
        #     elif j == 2:
        #         n = index3
        #     elif j == 3:
        #         m = index2
        #     me = BRepBuilderAPI_MakeEdge(tab.Value(m), tab.Value(n))
        #     if me.IsDone():
        #         builder.Add(comp, me.Edge())
    ex.Next()

# ==============================================================================
# Viz
# ==============================================================================

viewer = App()

# viewer.add(surface.to_mesh())
viewer.add(mesh)

for edge in edges:
    curve = OCCNurbsCurve.from_edge(edge)
    viewer.add(Polyline(curve.locus(resolution=16)),
               linecolor=(1, 0, 0),
               linewidth=5)

viewer.run()
from compas.geometry import Point
from compas.geometry import Polyline
from compas_occ.geometry import OCCNurbsCurve
from compas_view2.app import App

points1 = [Point(0, 0, 0), Point(1, 1, 0), Point(3, 0, 0)]
points2 = [Point(3, 0, 0), Point(4, -2, 0), Point(5, 0, 0)]

curve1 = OCCNurbsCurve.from_interpolation(points1)
curve2 = OCCNurbsCurve.from_interpolation(points2)

joined = curve1.joined(curve2)
curve1.join(curve2)

# ==============================================================================
# Visualisation
# ==============================================================================

view = App()

view.add(Polyline(curve1.locus()), linewidth=3, linecolor=(1, 0, 0))
view.add(Polyline(curve2.locus()), linewidth=3, linecolor=(0, 1, 0))
view.add(Polyline(joined.locus()), linewidth=3, linecolor=(0, 0, 1))

view.run()
# ==============================================================================
# JSON Data
# ==============================================================================

string = surface.to_jsonstring(pretty=True)

print(string)

other = OCCNurbsSurface.from_jsonstring(string)

print(surface == other)

# ==============================================================================
# Visualisation
# ==============================================================================

view = App()

u = surface.u_isocurve(0.5 * sum(surface.u_domain))
v = surface.v_isocurve(0.5 * sum(surface.v_domain))

view.add(Polyline(u.locus()), linewidth=1, linecolor=(0.3, 0.3, 0.3))
view.add(Polyline(v.locus()), linewidth=1, linecolor=(0.3, 0.3, 0.3))

for curve in surface.boundary():
    view.add(Polyline(curve.locus()), linewidth=2, linecolor=(0, 0, 0))

view.add(other.to_mesh(), show_edges=False)

view.run()
gyro = mesh_conway_gyro(mesh)
join = mesh_conway_join(mesh)
kis = mesh_conway_kis(mesh)
meta = mesh_conway_meta(mesh)
needle = mesh_conway_needle(mesh)
ortho = mesh_conway_ortho(mesh)
snub = mesh_conway_snub(mesh)
truncate = mesh_conway_truncate(mesh)

# ==============================================================================
# Viz
# ==============================================================================

T = Translation.from_vector

viewer = App()

viewer.add(ambo)
viewer.add(bevel.transformed(T([3, 0, 0])))
viewer.add(dual.transformed(T([6, 0, 0])))
viewer.add(expand.transformed(T([9, 0, 0])))

viewer.add(gyro.transformed(T([0, 4, 0])))
viewer.add(join.transformed(T([3, 4, 0])))
viewer.add(kis.transformed(T([6, 4, 0])))
viewer.add(meta.transformed(T([9, 4, 0])))

viewer.add(needle.transformed(T([0, 8, 0])))
viewer.add(ortho.transformed(T([3, 8, 0])))
viewer.add(snub.transformed(T([6, 8, 0])))
viewer.add(truncate.transformed(T([9, 8, 0])))
Exemple #13
0
mesh = model.mesh_to_compas()

lengths = [mesh.edge_length(*edge) for edge in mesh.edges()]

print(mesh.is_valid())
print(min(lengths))
print(max(lengths))

# omesh = model.mesh_to_openmesh()
# print(omesh)

# ==============================================================================
# Viz
# ==============================================================================

viewer = App(width=1600, height=900)

viewer.view.camera.rz = 0
viewer.view.camera.rx = -55
viewer.view.camera.tx = -5
viewer.view.camera.ty = -2
viewer.view.camera.distance = 10

viewer.add(mesh)

poa = Point(*plate.vertex_coordinates(poa))
start = poa + Vector(0, 0, 1)
vector = Vector(0, 0, -1)
load = Arrow(start, vector, body_width=0.03)

viewer.add(poa, size=20)
Exemple #14
0
    Rz = Rotation.from_axis_and_angle(Vector.Zaxis(),
                                      radians(i * 360 / 30),
                                      point=base)
    lines.append(line.transformed(Rz))

intersections = []
for line in lines:
    x = surface.intersections_with_line(line)
    if x:
        intersections.append(x[0])

# ==============================================================================
# Visualisation
# ==============================================================================

view = App(viewmode='ghosted')

for row in surface.points:
    view.add(Polyline(row),
             show_points=True,
             pointsize=20,
             pointcolor=(1, 0, 0),
             linewidth=2,
             linecolor=(0.3, 0.3, 0.3))

for col in zip(*surface.points):
    view.add(Polyline(col),
             show_points=True,
             pointsize=20,
             pointcolor=(1, 0, 0),
             linewidth=2,
Exemple #15
0
points2 = []
points2.append(Point(-4, 0, 2))
points2.append(Point(-2, 2, 0))
points2.append(Point(2, 3, -1))
points2.append(Point(3, 7, -2))
points2.append(Point(4, 9, -1))
spline2 = BSplineCurve.from_points(points2)

surface = BSplineSurface.from_fill(spline1, spline2)

U, V = meshgrid(surface.uspace(30), surface.vspace(20), 'ij')

frames = [surface.frame_at(u, v) for u, v in zip(flatten(U[1:]), flatten(V))]

# ==============================================================================
# Viz
# ==============================================================================

mesh = surface.to_vizmesh()
boundary = Polyline(
    mesh.vertices_attributes('xyz', keys=mesh.vertices_on_boundary()))

view = App()
view.add(mesh)
view.add(boundary, linewidth=2)

for frame in frames:
    view.add(frame, size=0.1)

view.run()
points2.append(Point(2, 3, -1))
points2.append(Point(3, 7, -2))
points2.append(Point(4, 9, -1))
spline2 = BSplineCurve.from_points(points2)

surface = BSplineSurface.from_fill(spline1, spline2)
line = Geom_Line(gp_Pnt(0, 4, 0), gp_Dir(0, 0, 1))

# ==============================================================================
# Intersection
# ==============================================================================

intersection = GeomAPI_IntCS(line, surface.occ_surface)

pnt = intersection.Point(1)
point = Point.from_occ(pnt)

# ==============================================================================
# Viz
# ==============================================================================

mesh = surface.to_vizmesh()
boundary = Polyline(
    mesh.vertices_attributes('xyz', keys=mesh.vertices_on_boundary()))

view = App()
view.add(mesh)
view.add(boundary, linewidth=2)
view.add(point, size=10, color=(1, 0, 0))
view.run()
Exemple #17
0
# Import
# ==============================================================================

meshes = compas.json_load(FILE_I)

# ==============================================================================
# Construct assembly
# ==============================================================================

assembly = Assembly()
for mesh in meshes:
    block = mesh.copy(cls=Block)
    assembly.add_block(block)

# ==============================================================================
# Export
# ==============================================================================

compas.json_dump(assembly, FILE_O)

# ==============================================================================
# Viz
# ==============================================================================

viewer = App()

for mesh in meshes:
    viewer.add(mesh, show_faces=False, show_edges=True)

viewer.run()
nurbscurve3 = NurbsCurve.from_interpolation(points3)
nurbscurve4 = NurbsCurve.from_interpolation(points4)
nurbscurve5 = NurbsCurve.from_interpolation(points5)
nurbscurve6 = NurbsCurve.from_interpolation(points6)

nurbssurface_4curves = NurbsSurface.from_fill(nurbscurve3,
                                              nurbscurve4,
                                              nurbscurve5,
                                              nurbscurve6,
                                              style='curved')

# ==============================================================================
# Visualisation
# ==============================================================================

view = App()

view.add(Polyline(nurbscurve1.locus()), linewidth=3, linecolor=(1, 0, 0))
view.add(Polyline(nurbscurve2.locus()), linewidth=3, linecolor=(0, 1, 0))

view.add(Polyline(nurbscurve3.locus()), linewidth=3, linecolor=(1, 0, 0))
view.add(Polyline(nurbscurve4.locus()), linewidth=3, linecolor=(0, 1, 0))
view.add(Polyline(nurbscurve5.locus()), linewidth=3, linecolor=(1, 0, 1))
view.add(Polyline(nurbscurve6.locus()), linewidth=3, linecolor=(0, 0, 1))

view.add(nurbssurface_2curves.to_mesh(nu=10))
view.add(nurbssurface_4curves.to_mesh(nu=10))

view.run()
Exemple #19
0
sphere = Sphere(Point(1, 1, 1), 1)
sphere = Mesh.from_shape(sphere, u=30, v=30)
sphere.quads_to_triangles()

B = sphere.to_vertices_and_faces()

# ==============================================================================
# Remesh the sphere
# ==============================================================================

B = remesh(B, 0.3, 10)

# ==============================================================================
# Compute the boolean mesh
# ==============================================================================

V, F = boolean_union(A, B)

mesh = Mesh.from_vertices_and_faces(V, F)

# ==============================================================================
# Visualize
# ==============================================================================

viewer = App()

viewer.add(mesh, show_edges=True)

viewer.run()
Exemple #20
0
    planes.append(plane)

# ==============================================================================
# Slice
# ==============================================================================

M = benchy.to_vertices_and_faces()

pointsets = slice_mesh(M, planes)

# ==============================================================================
# Process output
# ==============================================================================

polylines = []
for points in pointsets:
    points = [Point(*point) for point in points]
    polyline = Polyline(points)
    polylines.append(polyline)

# ==============================================================================
# Visualize
# ==============================================================================

viewer = App()

for polyline in polylines:
    viewer.add(polyline, linecolor=(1, 0, 0))

viewer.run()
Exemple #21
0
s = 1 / (p - o).length
S = Scale.from_factors([s, s, s])

dodeca.transform(T * T * T * S)

p = Point(*icosa.vertex_coordinates(icosa.get_any_vertex()))
s = 1 / (p - o).length
S = Scale.from_factors([s, s, s])

icosa.transform(T * T * T * T * S)

# ==============================================================================
# Viz
# ==============================================================================

viewer = App()

primal = {
    'show_faces': False,
    'show_edges': True,
    'show_vertices': False,
    'linecolor': (0, 0, 0),
    'linewidth': 2,
}

dual = {
    'show_faces': True,
    'show_edges': True,
    'show_vertices': True,
    'facecolor': (0, 0, 1),
    'linecolor': (0, 1, 1),
Exemple #22
0
pointsets = intersection_mesh_mesh(A, B)

# ==============================================================================
# Process output
# ==============================================================================

polylines = []
for points in pointsets:
    points = [Point(*point) for point in points]
    polyline = Polyline(points)
    polylines.append(polyline)

# ==============================================================================
# Visualize
# ==============================================================================

viewer = App()

viewer.add(Mesh.from_vertices_and_faces(*A), facecolor=(1, 0, 0), opacity=0.7)
viewer.add(Mesh.from_vertices_and_faces(*B), facecolor=(0, 1, 0), opacity=0.7)

for polyline in polylines:
    viewer.add(polyline,
               linecolor=(0, 0, 1),
               linewidth=3,
               pointcolor=(1, 0, 0),
               pointsize=10,
               show_points=True)

viewer.run()
Exemple #23
0
# ==============================================================================

T = Translation.from_vector(Point(0, 0, 0) - Point(*before.centroid()))
S = Scale.from_factors([100, 100, 100])
R = Rotation.from_axis_and_angle([1, 0, 0], radians(90))

before.transform(R * S * T)

# ==============================================================================
# Remesh
# ==============================================================================

L = sum(before.edge_length(*edge)
        for edge in before.edges()) / before.number_of_edges()

V, F = trimesh_remesh(before.to_vertices_and_faces(), 3 * L)
after = Mesh.from_vertices_and_faces(V, F)

# ==============================================================================
# Viz
# ==============================================================================

viewer = App()

box = Box.from_bounding_box(before.bounding_box())
dx = 1.5 * box.xsize

viewer.add(before)
viewer.add(after.transformed(Translation.from_vector([dx, 0, 0])))
viewer.run()
Exemple #24
0
line = Line(* box.diagonal)

# ==============================================================================
# Slices
# ==============================================================================

N = 9
slices = []

a = line.start
for i in range(1, N + 1):
    b = a + line.direction * i * 0.1 * line.length
    plane = Plane(b, line.direction)
    mesh, B = mesh.slice_plane(plane)
    slices.append(B)

slices.append(mesh)

# ==============================================================================
# Exploded viz
# ==============================================================================

viewer = App()

for i, mesh in enumerate(slices):
    T = Translation.from_vector(line.direction * i * 0.05 * line.length)
    viewer.add(mesh.transformed(T), facecolor=i_to_rgb(i / N, normalize=True))

viewer.run()
Exemple #25
0
from compas_occ.geometry import OCCNurbsCurve
from compas_view2.app import App

pointsA = [Point(0, 0, 0), Point(3, 6, 0), Point(6, -3, 3), Point(10, 0, 0)]
curveA = OCCNurbsCurve.from_points(pointsA)

curveA.segment(u=0.2, v=0.5)

print(curveA.domain)

pointsB = [Point(0, -1, 0), Point(3, 5, 0), Point(6, -4, 3), Point(10, -1, 0)]
curveB = OCCNurbsCurve.from_points(pointsB)

segment = curveB.segmented(u=0.2, v=0.5)

print(curveB.domain)
print(segment.domain)

# ==============================================================================
# Visualisation
# ==============================================================================

view = App()

view.add(Polyline(curveA.locus()), linewidth=4, linecolor=(1, 0, 0))

view.add(Polyline(curveB.locus()), linewidth=1, linecolor=(0, 0, 0))
view.add(Polyline(segment.locus()), linewidth=4, linecolor=(0, 1, 0))

view.run()
Exemple #26
0
# ==============================================================================

assembly = Assembly()
for mesh in meshes:
    block = mesh.copy(cls=Block)
    assembly.add_block(block)

# ==============================================================================
# Export
# ==============================================================================

compas.json_dump(assembly, FILE_O)

# ==============================================================================
# Viz
# ==============================================================================

viewer = App()

nodes = []
blocks = []

for node in assembly.nodes():
    nodes.append(Point(* assembly.node_coordinates(node)))
    blocks.append(assembly.node_attribute(node, 'block'))

viewer.add(Collection(nodes))
viewer.add(Collection(blocks), show_faces=True, show_edges=True, facecolor=(0.8, 0.8, 0.8), linecolor=(0, 0, 0))

viewer.run()
Exemple #27
0
# ==============================================================================
# Compute the boolean difference
# ==============================================================================

V, F = boolean_difference(A, B)

difference = Mesh.from_vertices_and_faces(V, F)

# ==============================================================================
# Compute the boolean intersection
# ==============================================================================

V, F = boolean_intersection(A, B)

intersection = Mesh.from_vertices_and_faces(V, F)

# ==============================================================================
# Visualize
# ==============================================================================

viewer = App()

viewer.add(box, facecolor=(1, 0, 0), opacity=0.5)
viewer.add(sphere, facecolor=(0, 0, 1), opacity=0.5)

viewer.add(union.transformed(Translation.from_vector([1 * 1.5 * width, 0, 0])), facecolor=(1, 0, 1))
viewer.add(difference.transformed(Translation.from_vector([2 * 1.5 * width, 0, 0])), show_faces=False, show_edges=True, linecolor=(1, 0, 0))
viewer.add(intersection.transformed(Translation.from_vector([2 * 1.5 * width, 0, 0])), facecolor=(0, 1, 0))

viewer.run()
Exemple #28
0
spline1 = BSplineCurve.from_points(points1)

points2 = []
points2.append(Point(-4, 0, 2))
points2.append(Point(-2, 2, 0))
points2.append(Point(2, 3, -1))
points2.append(Point(3, 7, -2))
points2.append(Point(4, 9, -1))
spline2 = BSplineCurve.from_points(points2)

surface = BSplineSurface.from_fill(spline1, spline2)
points = surface.xyz(nu=30, nv=20)

n = len(points)

colors = [i_to_rgb(i / n, normalize=True) for i in range(n)]

# ==============================================================================
# Viz
# ==============================================================================

mesh = surface.to_vizmesh()
boundary = Polyline(
    mesh.vertices_attributes('xyz', keys=mesh.vertices_on_boundary()))

view = App()
view.add(mesh)
view.add(boundary, linewidth=2)
view.add(Collection(points), colors=colors, size=10)
view.run()
from compas.geometry import Vector, Point, Plane
from compas.geometry import Polyline
from compas.geometry import Circle
from compas_occ.geometry import OCCNurbsCurve
from compas_view2.app import App

circle = Circle(Plane(Point(0, 0, 0), Vector(0, 0, 1)), 1.0)
curve = OCCNurbsCurve.from_circle(circle)

# ==============================================================================
# Visualisation
# ==============================================================================

view = App()

view.add(Polyline(curve.locus()), linewidth=3)
view.add(Polyline(curve.points),
         show_points=True,
         pointsize=20,
         pointcolor=(1, 0, 0),
         linewidth=1,
         linecolor=(0.3, 0.3, 0.3))

view.run()
Exemple #30
0
model.generate_mesh()
model.optimize_mesh()

# ==============================================================================
# COMPAS mesh
# ==============================================================================

mesh = model.mesh_to_compas()

mesh.transform(Translation.from_vector([4 * R, 0, 0]))

# ==============================================================================
# Visualization with viewer
# ==============================================================================

viewer = App(width=1600, height=900)

viewer.view.camera.rz = -35
viewer.view.camera.rx = -75
viewer.view.camera.tx = -2 * R
viewer.view.camera.ty = 1
viewer.view.camera.distance = 12

viewer.add(sphere, u=32, v=32, opacity=0.5, color=(1, 0, 0))
viewer.add(box, opacity=0.5, color=(0, 1, 0))
viewer.add(cylx, u=32, opacity=0.5, color=(0, 0, 1))
viewer.add(cyly, u=32, opacity=0.5, color=(0, 0, 1))
viewer.add(cylz, u=32, opacity=0.5, color=(0, 0, 1))

viewer.add(mesh)
viewer.run()