potree module¶
Potree point cloud viewer implementation of the map widget.
PotreeMap (MapWidget)
¶
Potree point cloud viewer implementation of the map widget.
Source code in anymap/potree.py
class PotreeMap(MapWidget):
"""Potree point cloud viewer implementation of the map widget."""
# Potree-specific traits
# Appearance
point_budget = traitlets.Int(1_000_000).tag(sync=True)
fov = traitlets.Float(60.0).tag(sync=True)
background = traitlets.Enum(
values=["skybox", "gradient", "black", "white", "none"],
default_value="gradient",
).tag(sync=True)
# Appearance: Eye-Dome Lighting
edl_enabled = traitlets.Bool(True).tag(sync=True)
edl_radius = traitlets.Float(1.4).tag(sync=True)
edl_strength = traitlets.Float(0.4).tag(sync=True)
edl_opacity = traitlets.Float(1.0).tag(sync=True)
description = traitlets.Unicode("").tag(sync=True)
point_cloud_url = traitlets.Unicode("").tag(sync=True)
point_size = traitlets.Float(1.0).tag(sync=True)
point_size_type = traitlets.Unicode("adaptive").tag(
sync=True
) # "fixed", "adaptive", "attenuation"
point_shape = traitlets.Unicode("square").tag(sync=True) # "square", "circle"
min_node_size = traitlets.Float(100.0).tag(sync=True)
show_grid = traitlets.Bool(False).tag(sync=True)
grid_size = traitlets.Float(10.0).tag(sync=True)
grid_color = traitlets.Unicode("#aaaaaa").tag(sync=True)
background_color = traitlets.Unicode("#000000").tag(sync=True)
# Camera controls
camera_position = traitlets.List([0.0, 0.0, 10.0]).tag(sync=True)
camera_target = traitlets.List([0.0, 0.0, 0.0]).tag(sync=True)
near_clip = traitlets.Float(0.1).tag(sync=True)
far_clip = traitlets.Float(1000.0).tag(sync=True)
# Define the JavaScript module path
_esm = _esm_potree
_css = _css_potree
POTREE_LIBS_DIR = traitlets.Unicode(read_only=True).tag(sync=True)
def __init__(
self,
point_cloud_url: str = "",
width: str = "100%",
height: str = "600px",
point_budget: int = 1_000_000,
point_size: float = 1.0,
point_size_type: str = "adaptive",
point_shape: str = "square",
camera_position: List[float] = [0.0, 0.0, 10.0],
camera_target: List[float] = [0.0, 0.0, 0.0],
fov: float = 60.0,
background_color: str = "#000000",
edl_enabled: bool = True,
show_grid: bool = False,
quiet: bool = False,
**kwargs,
):
"""Initialize Potree map widget.
Args:
point_cloud_url: URL to the point cloud metadata.json file
width: Widget width
height: Widget height
point_budget: Point budget: influences the point density on screen
point_size: Size of rendered points
point_size_type: How point size is calculated ("fixed", "adaptive", "attenuation")
point_shape: Shape of rendered points ("square", "circle")
camera_position: Initial camera position [x, y, z]
camera_target: Camera look-at target [x, y, z]
fov: Field of view in degrees
background_color: Background color of the viewer
edl_enabled: Enable Eye Dome Lighting for better depth perception
show_grid: Show coordinate grid
quiet: Don't print any information messages
"""
self.JUPYTER_ROOT = _get_jupyter_root()
if not self.JUPYTER_ROOT:
warnings.warn(
"PotreeMap is currently only supported through a JupyterLab environment."
)
self._css = """
.potree-warning {
font-family: sans-serif;
padding: 1rem;
background-color: #fff3cd;
color: #856404;
border: 1px solid #ffeeba;
border-radius: 8px;
margin: 1rem 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
"""
self._esm = """
function render({ model, el }) {
let div = document.createElement("div");
div.className = "potree-warning";
const msg = document.createTextNode("🚫 PotreeMap is not yet supported in your environment. Try running it in JupyterLab instead.");
div.appendChild(msg);
el.appendChild(div);
}
export default { render };
"""
super().__init__()
return
self.set_trait("POTREE_LIBS_DIR", str("/files/potreelibs"))
got_potree_libs = _get_potree_libs(self.JUPYTER_ROOT, quiet=quiet)
if not got_potree_libs:
raise RuntimeError("Something went wrong -- could not get potree libs")
super().__init__(
width=width,
height=height,
point_budget=point_budget,
point_cloud_url=point_cloud_url,
point_size=point_size,
point_size_type=point_size_type,
point_shape=point_shape,
camera_position=camera_position,
camera_target=camera_target,
fov=fov,
background_color=background_color,
edl_enabled=edl_enabled,
show_grid=show_grid,
**kwargs,
)
def set_description(self, description: str) -> None:
"""Sets the description."""
self.description = description
# Appearance
def set_point_budget(self, point_budget: int) -> None:
"""Sets the point budget"""
self.point_budget = point_budget
def load_point_cloud(
self, point_cloud_url: str, point_cloud_name: Optional[str] = None
) -> None:
"""Load a point cloud from URL.
Args:
point_cloud_url: URL to the point cloud metadata.json file
point_cloud_name: Optional name for the point cloud
"""
self.point_cloud_url = point_cloud_url
options = {"url": point_cloud_url}
if point_cloud_name:
options["name"] = point_cloud_name
self.call_js_method("loadPointCloud", options)
def set_point_size(self, size: float) -> None:
"""Set the point size."""
self.point_size = size
def set_point_size_type(self, size_type: str) -> None:
"""Set the point size type.
Args:
size_type: "fixed", "adaptive", or "attenuation"
"""
if size_type not in ["fixed", "adaptive", "attenuation"]:
raise ValueError("size_type must be 'fixed', 'adaptive', or 'attenuation'")
self.point_size_type = size_type
def set_point_shape(self, shape: str) -> None:
"""Set the point shape.
Args:
shape: "square" or "circle"
"""
if shape not in ["square", "circle"]:
raise ValueError("shape must be 'square' or 'circle'")
self.point_shape = shape
def set_camera_position(
self, position: List[float], target: Optional[List[float]] = None
) -> None:
"""Set camera position and optionally target.
Args:
position: Camera position [x, y, z]
target: Camera target [x, y, z] (optional)
"""
self.camera_position = position
if target:
self.camera_target = target
def fit_to_screen(self) -> None:
"""Fit the point cloud to the screen."""
self.call_js_method("fitToScreen")
def enable_edl(self, enabled: bool = True) -> None:
"""Enable or disable Eye Dome Lighting.
Args:
enabled: Whether to enable EDL
"""
self.edl_enabled = enabled
def set_edl_settings(
self, radius: float = 1.4, strength: float = 0.4, opacity: float = 1.0
) -> None:
"""Set Eye Dome Lighting parameters.
Args:
radius: EDL radius
strength: EDL strength
opacity: EDL opacity
"""
self.edl_radius = radius
self.edl_strength = strength
self.edl_opacity = opacity
def show_coordinate_grid(
self, show: bool = True, size: float = 10.0, color: str = "#aaaaaa"
) -> None:
"""Show or hide coordinate grid.
Args:
show: Whether to show the grid
size: Grid size
color: Grid color
"""
self.show_grid = show
self.grid_size = size
self.grid_color = color
def set_background_color(self, color: str) -> None:
"""Set the background color.
Args:
color: Background color (hex format like "#000000")
"""
self.background_color = color
def clear_point_clouds(self) -> None:
"""Clear all point clouds from the viewer."""
self.call_js_method("clearPointClouds")
def get_camera_position(self) -> List[float]:
"""Get current camera position."""
return list(self.camera_position)
def get_camera_target(self) -> List[float]:
"""Get current camera target."""
return list(self.camera_target)
def take_screenshot(self) -> None:
"""Take a screenshot of the current view."""
self.call_js_method("takeScreenshot")
def set_fov(self, fov: float) -> None:
"""Set field of view.
Args:
fov: Field of view in degrees
"""
self.fov = fov
def set_clip_distances(self, near: float, far: float) -> None:
"""Set near and far clipping distances.
Args:
near: Near clipping distance
far: Far clipping distance
"""
self.near_clip = near
self.far_clip = far
def add_measurement(self, measurement_type: str = "distance") -> None:
"""Add measurement tool.
Args:
measurement_type: Type of measurement ("distance", "area", "volume", "angle")
"""
self.call_js_method("addMeasurement", measurement_type)
def clear_measurements(self) -> None:
"""Clear all measurements."""
self.call_js_method("clearMeasurements")
def set_quality(self, quality: str = "medium") -> None:
"""Set rendering quality.
Args:
quality: Rendering quality ("low", "medium", "high")
"""
if quality not in ["low", "medium", "high"]:
raise ValueError("quality must be 'low', 'medium', or 'high'")
self.call_js_method("setQuality", quality)
def load_multiple_point_clouds(self, point_clouds: List[Dict[str, str]]) -> None:
"""Load multiple point clouds.
Args:
point_clouds: List of point cloud configs with 'url' and optional 'name' keys
"""
self.call_js_method("loadMultiplePointClouds", point_clouds)
def set_classification_visibility(self, classifications: Dict[int, bool]) -> None:
"""Set visibility of point classifications.
Args:
classifications: Dict mapping classification codes to visibility
"""
self.call_js_method("setClassificationVisibility", classifications)
def filter_by_elevation(
self,
min_elevation: Optional[float] = None,
max_elevation: Optional[float] = None,
) -> None:
"""Filter points by elevation.
Args:
min_elevation: Minimum elevation to show
max_elevation: Maximum elevation to show
"""
options = {}
if min_elevation is not None:
options["min"] = min_elevation
if max_elevation is not None:
options["max"] = max_elevation
self.call_js_method("filterByElevation", options)
def clear_filters(self) -> None:
"""Clear all filters."""
self.call_js_method("clearFilters")
__init__(self, point_cloud_url='', width='100%', height='600px', point_budget=1000000, point_size=1.0, point_size_type='adaptive', point_shape='square', camera_position=[0.0, 0.0, 10.0], camera_target=[0.0, 0.0, 0.0], fov=60.0, background_color='#000000', edl_enabled=True, show_grid=False, quiet=False, **kwargs)
special
¶
Initialize Potree map widget.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
point_cloud_url |
str |
URL to the point cloud metadata.json file |
'' |
width |
str |
Widget width |
'100%' |
height |
str |
Widget height |
'600px' |
point_budget |
int |
Point budget: influences the point density on screen |
1000000 |
point_size |
float |
Size of rendered points |
1.0 |
point_size_type |
str |
How point size is calculated ("fixed", "adaptive", "attenuation") |
'adaptive' |
point_shape |
str |
Shape of rendered points ("square", "circle") |
'square' |
camera_position |
List[float] |
Initial camera position [x, y, z] |
[0.0, 0.0, 10.0] |
camera_target |
List[float] |
Camera look-at target [x, y, z] |
[0.0, 0.0, 0.0] |
fov |
float |
Field of view in degrees |
60.0 |
background_color |
str |
Background color of the viewer |
'#000000' |
edl_enabled |
bool |
Enable Eye Dome Lighting for better depth perception |
True |
show_grid |
bool |
Show coordinate grid |
False |
quiet |
bool |
Don't print any information messages |
False |
Source code in anymap/potree.py
def __init__(
self,
point_cloud_url: str = "",
width: str = "100%",
height: str = "600px",
point_budget: int = 1_000_000,
point_size: float = 1.0,
point_size_type: str = "adaptive",
point_shape: str = "square",
camera_position: List[float] = [0.0, 0.0, 10.0],
camera_target: List[float] = [0.0, 0.0, 0.0],
fov: float = 60.0,
background_color: str = "#000000",
edl_enabled: bool = True,
show_grid: bool = False,
quiet: bool = False,
**kwargs,
):
"""Initialize Potree map widget.
Args:
point_cloud_url: URL to the point cloud metadata.json file
width: Widget width
height: Widget height
point_budget: Point budget: influences the point density on screen
point_size: Size of rendered points
point_size_type: How point size is calculated ("fixed", "adaptive", "attenuation")
point_shape: Shape of rendered points ("square", "circle")
camera_position: Initial camera position [x, y, z]
camera_target: Camera look-at target [x, y, z]
fov: Field of view in degrees
background_color: Background color of the viewer
edl_enabled: Enable Eye Dome Lighting for better depth perception
show_grid: Show coordinate grid
quiet: Don't print any information messages
"""
self.JUPYTER_ROOT = _get_jupyter_root()
if not self.JUPYTER_ROOT:
warnings.warn(
"PotreeMap is currently only supported through a JupyterLab environment."
)
self._css = """
.potree-warning {
font-family: sans-serif;
padding: 1rem;
background-color: #fff3cd;
color: #856404;
border: 1px solid #ffeeba;
border-radius: 8px;
margin: 1rem 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
"""
self._esm = """
function render({ model, el }) {
let div = document.createElement("div");
div.className = "potree-warning";
const msg = document.createTextNode("🚫 PotreeMap is not yet supported in your environment. Try running it in JupyterLab instead.");
div.appendChild(msg);
el.appendChild(div);
}
export default { render };
"""
super().__init__()
return
self.set_trait("POTREE_LIBS_DIR", str("/files/potreelibs"))
got_potree_libs = _get_potree_libs(self.JUPYTER_ROOT, quiet=quiet)
if not got_potree_libs:
raise RuntimeError("Something went wrong -- could not get potree libs")
super().__init__(
width=width,
height=height,
point_budget=point_budget,
point_cloud_url=point_cloud_url,
point_size=point_size,
point_size_type=point_size_type,
point_shape=point_shape,
camera_position=camera_position,
camera_target=camera_target,
fov=fov,
background_color=background_color,
edl_enabled=edl_enabled,
show_grid=show_grid,
**kwargs,
)
add_measurement(self, measurement_type='distance')
¶
Add measurement tool.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
measurement_type |
str |
Type of measurement ("distance", "area", "volume", "angle") |
'distance' |
Source code in anymap/potree.py
def add_measurement(self, measurement_type: str = "distance") -> None:
"""Add measurement tool.
Args:
measurement_type: Type of measurement ("distance", "area", "volume", "angle")
"""
self.call_js_method("addMeasurement", measurement_type)
clear_filters(self)
¶
Clear all filters.
Source code in anymap/potree.py
def clear_filters(self) -> None:
"""Clear all filters."""
self.call_js_method("clearFilters")
clear_measurements(self)
¶
Clear all measurements.
Source code in anymap/potree.py
def clear_measurements(self) -> None:
"""Clear all measurements."""
self.call_js_method("clearMeasurements")
clear_point_clouds(self)
¶
Clear all point clouds from the viewer.
Source code in anymap/potree.py
def clear_point_clouds(self) -> None:
"""Clear all point clouds from the viewer."""
self.call_js_method("clearPointClouds")
enable_edl(self, enabled=True)
¶
Enable or disable Eye Dome Lighting.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
enabled |
bool |
Whether to enable EDL |
True |
Source code in anymap/potree.py
def enable_edl(self, enabled: bool = True) -> None:
"""Enable or disable Eye Dome Lighting.
Args:
enabled: Whether to enable EDL
"""
self.edl_enabled = enabled
filter_by_elevation(self, min_elevation=None, max_elevation=None)
¶
Filter points by elevation.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
min_elevation |
Optional[float] |
Minimum elevation to show |
None |
max_elevation |
Optional[float] |
Maximum elevation to show |
None |
Source code in anymap/potree.py
def filter_by_elevation(
self,
min_elevation: Optional[float] = None,
max_elevation: Optional[float] = None,
) -> None:
"""Filter points by elevation.
Args:
min_elevation: Minimum elevation to show
max_elevation: Maximum elevation to show
"""
options = {}
if min_elevation is not None:
options["min"] = min_elevation
if max_elevation is not None:
options["max"] = max_elevation
self.call_js_method("filterByElevation", options)
fit_to_screen(self)
¶
Fit the point cloud to the screen.
Source code in anymap/potree.py
def fit_to_screen(self) -> None:
"""Fit the point cloud to the screen."""
self.call_js_method("fitToScreen")
get_camera_position(self)
¶
Get current camera position.
Source code in anymap/potree.py
def get_camera_position(self) -> List[float]:
"""Get current camera position."""
return list(self.camera_position)
get_camera_target(self)
¶
Get current camera target.
Source code in anymap/potree.py
def get_camera_target(self) -> List[float]:
"""Get current camera target."""
return list(self.camera_target)
load_multiple_point_clouds(self, point_clouds)
¶
Load multiple point clouds.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
point_clouds |
List[Dict[str, str]] |
List of point cloud configs with 'url' and optional 'name' keys |
required |
Source code in anymap/potree.py
def load_multiple_point_clouds(self, point_clouds: List[Dict[str, str]]) -> None:
"""Load multiple point clouds.
Args:
point_clouds: List of point cloud configs with 'url' and optional 'name' keys
"""
self.call_js_method("loadMultiplePointClouds", point_clouds)
load_point_cloud(self, point_cloud_url, point_cloud_name=None)
¶
Load a point cloud from URL.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
point_cloud_url |
str |
URL to the point cloud metadata.json file |
required |
point_cloud_name |
Optional[str] |
Optional name for the point cloud |
None |
Source code in anymap/potree.py
def load_point_cloud(
self, point_cloud_url: str, point_cloud_name: Optional[str] = None
) -> None:
"""Load a point cloud from URL.
Args:
point_cloud_url: URL to the point cloud metadata.json file
point_cloud_name: Optional name for the point cloud
"""
self.point_cloud_url = point_cloud_url
options = {"url": point_cloud_url}
if point_cloud_name:
options["name"] = point_cloud_name
self.call_js_method("loadPointCloud", options)
set_background_color(self, color)
¶
Set the background color.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
color |
str |
Background color (hex format like "#000000") |
required |
Source code in anymap/potree.py
def set_background_color(self, color: str) -> None:
"""Set the background color.
Args:
color: Background color (hex format like "#000000")
"""
self.background_color = color
set_camera_position(self, position, target=None)
¶
Set camera position and optionally target.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
position |
List[float] |
Camera position [x, y, z] |
required |
target |
Optional[List[float]] |
Camera target [x, y, z] (optional) |
None |
Source code in anymap/potree.py
def set_camera_position(
self, position: List[float], target: Optional[List[float]] = None
) -> None:
"""Set camera position and optionally target.
Args:
position: Camera position [x, y, z]
target: Camera target [x, y, z] (optional)
"""
self.camera_position = position
if target:
self.camera_target = target
set_classification_visibility(self, classifications)
¶
Set visibility of point classifications.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
classifications |
Dict[int, bool] |
Dict mapping classification codes to visibility |
required |
Source code in anymap/potree.py
def set_classification_visibility(self, classifications: Dict[int, bool]) -> None:
"""Set visibility of point classifications.
Args:
classifications: Dict mapping classification codes to visibility
"""
self.call_js_method("setClassificationVisibility", classifications)
set_clip_distances(self, near, far)
¶
Set near and far clipping distances.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
near |
float |
Near clipping distance |
required |
far |
float |
Far clipping distance |
required |
Source code in anymap/potree.py
def set_clip_distances(self, near: float, far: float) -> None:
"""Set near and far clipping distances.
Args:
near: Near clipping distance
far: Far clipping distance
"""
self.near_clip = near
self.far_clip = far
set_description(self, description)
¶
Sets the description.
Source code in anymap/potree.py
def set_description(self, description: str) -> None:
"""Sets the description."""
self.description = description
set_edl_settings(self, radius=1.4, strength=0.4, opacity=1.0)
¶
Set Eye Dome Lighting parameters.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
radius |
float |
EDL radius |
1.4 |
strength |
float |
EDL strength |
0.4 |
opacity |
float |
EDL opacity |
1.0 |
Source code in anymap/potree.py
def set_edl_settings(
self, radius: float = 1.4, strength: float = 0.4, opacity: float = 1.0
) -> None:
"""Set Eye Dome Lighting parameters.
Args:
radius: EDL radius
strength: EDL strength
opacity: EDL opacity
"""
self.edl_radius = radius
self.edl_strength = strength
self.edl_opacity = opacity
set_fov(self, fov)
¶
Set field of view.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
fov |
float |
Field of view in degrees |
required |
Source code in anymap/potree.py
def set_fov(self, fov: float) -> None:
"""Set field of view.
Args:
fov: Field of view in degrees
"""
self.fov = fov
set_point_budget(self, point_budget)
¶
Sets the point budget
Source code in anymap/potree.py
def set_point_budget(self, point_budget: int) -> None:
"""Sets the point budget"""
self.point_budget = point_budget
set_point_shape(self, shape)
¶
Set the point shape.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
shape |
str |
"square" or "circle" |
required |
Source code in anymap/potree.py
def set_point_shape(self, shape: str) -> None:
"""Set the point shape.
Args:
shape: "square" or "circle"
"""
if shape not in ["square", "circle"]:
raise ValueError("shape must be 'square' or 'circle'")
self.point_shape = shape
set_point_size(self, size)
¶
Set the point size.
Source code in anymap/potree.py
def set_point_size(self, size: float) -> None:
"""Set the point size."""
self.point_size = size
set_point_size_type(self, size_type)
¶
Set the point size type.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
size_type |
str |
"fixed", "adaptive", or "attenuation" |
required |
Source code in anymap/potree.py
def set_point_size_type(self, size_type: str) -> None:
"""Set the point size type.
Args:
size_type: "fixed", "adaptive", or "attenuation"
"""
if size_type not in ["fixed", "adaptive", "attenuation"]:
raise ValueError("size_type must be 'fixed', 'adaptive', or 'attenuation'")
self.point_size_type = size_type
set_quality(self, quality='medium')
¶
Set rendering quality.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
quality |
str |
Rendering quality ("low", "medium", "high") |
'medium' |
Source code in anymap/potree.py
def set_quality(self, quality: str = "medium") -> None:
"""Set rendering quality.
Args:
quality: Rendering quality ("low", "medium", "high")
"""
if quality not in ["low", "medium", "high"]:
raise ValueError("quality must be 'low', 'medium', or 'high'")
self.call_js_method("setQuality", quality)
show_coordinate_grid(self, show=True, size=10.0, color='#aaaaaa')
¶
Show or hide coordinate grid.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
show |
bool |
Whether to show the grid |
True |
size |
float |
Grid size |
10.0 |
color |
str |
Grid color |
'#aaaaaa' |
Source code in anymap/potree.py
def show_coordinate_grid(
self, show: bool = True, size: float = 10.0, color: str = "#aaaaaa"
) -> None:
"""Show or hide coordinate grid.
Args:
show: Whether to show the grid
size: Grid size
color: Grid color
"""
self.show_grid = show
self.grid_size = size
self.grid_color = color
take_screenshot(self)
¶
Take a screenshot of the current view.
Source code in anymap/potree.py
def take_screenshot(self) -> None:
"""Take a screenshot of the current view."""
self.call_js_method("takeScreenshot")