VectorField
FluxRender.entities.VectorField
VectorField(vec_function, color_mapper: ColorMapper = ColorMapper(), color_property: Property = Property.VELOCITY, color_clipping_percentiles: Sequence[float] = (5.0, 95.0), spacing_x=None, spacing_y=None, normalized: bool = True, length=None, thickness=2, mode: FieldMode = FieldMode.ZOOM_DENSITY_ADAPTIVE, arrow_size=15, arrow_style=ArrowStyle.HARPOON, draw_arrows: bool = True, antyaliasing: bool = True, max_vectors: int = 10000, details_factor: int = 6, chaos_sensitivity: float = 3.0, max_length_reduction: float = 0.6, base_angle_vector=None, custom_color_function=None)
Bases: VectorEntity
A visual entity that renders a mathematical vector field using directional arrows.
The VectorField acts as the static, geometric counterpart to the dynamic ParticleSystem. It queries the underlying mathematical engine across a spatial grid and visualizes the results as a structured collection of arrows, where each arrow represents the local magnitude and direction of the field at a specific point in space.
This class excels at topological analysis. It features highly advanced rendering modes (such as FieldMode.ZOOM_DENSITY_ADAPTIVE) that dynamically recalculate grid spacing based on the camera's zoom level and local mathematical chaos. By coupling it with a ColorMapper, complex physical properties (like divergence, curl, or custom tensor evaluations) can be instantly translated into intuitive, color-coded visual maps.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vec_function
|
Callable / VectorMathEngine
|
The math driving the flow. A function taking (x, y) and optionally (t) returning vector components (dx, dy), or a pre-built VectorMathEngine. IMPORTANT REFERENCE NOTE: If you pass an existing VectorMathEngine instance
AND simultaneously provide overriding parameters (such as |
required |
color_mapper
|
ColorMapper
|
An instance of a ColorMapper that maps vector properties to colors. If min_value and max_value are not provided, they will be automatically calculated. (Default: ColorMapper()) |
ColorMapper()
|
color_property
|
Property
|
The vector property used for coloring (e.g., velocity, divergence, curl, angle, or a custom function). (Default: Property.VELOCITY) |
VELOCITY
|
color_clipping_percentiles
|
tuple
|
The percentiles used to clip the color values. Defaults to (5.0, 95.0). |
(5.0, 95.0)
|
spacing_x
|
float
|
Horizontal spacing between vectors. Units depend on the mode:
|
None
|
spacing_y
|
float
|
The vertical spacing between vectors. Same units and defaults as spacing_x. |
None
|
normalized
|
bool
|
Whether to normalize vectors to unit length for visualization purposes. (Default: True) |
True
|
length
|
float
|
The base length of the vectors. Units depend on the mode:
|
None
|
thickness
|
float
|
The thickness of the drawn vectors in pixels. (Default: 2) |
2
|
mode
|
FieldMode
|
The mode of vector field rendering determining spacing and scaling (default: FieldMode.ZOOM_DENSITY_ADAPTIVE):
|
ZOOM_DENSITY_ADAPTIVE
|
arrow_size
|
float
|
The size of the arrowheads in pixels. (Default: 15) |
15
|
arrow_style
|
ArrowStyle
|
The visual style of the arrowheads (e.g., OPEN, TRIANGLE_TIGHT, HARPOON). (Default: HARPOON) |
HARPOON
|
draw_arrows
|
bool
|
Whether to draw arrowheads at the end of vectors. |
True
|
antyaliasing
|
bool
|
Whether to apply anti-aliasing for smoother visuals. (Default: True) |
True
|
max_vectors
|
int
|
Maximum number of vectors to render. (Default: 10000) |
10000
|
details_factor
|
int
|
[Density Adaptive] How many times denser is the arrow spacing compared to the standard spacing at points with the greatest chaos. (Default: 6) |
6
|
chaos_sensitivity
|
float
|
[Density Adaptive] How fast the density increases with chaos (directional derivatives magnitude). (Default: 3.0) |
3.0
|
max_length_reduction
|
float
|
[Density Adaptive] The maximum length reduction for arrows in the most chaotic areas. (Default: 0.6) |
0.6
|
base_angle_vector
|
tuple, list, or Callable
|
[Property.ANGLE] The reference vector used to calculate angles. Defined as:
|
None
|
custom_color_function
|
Callable
|
[Property.CUSTOM] A user-defined function for calculating colors. To maximize performance, the engine strictly avoids redundant math. Since the VectorField or ParticleSystem already evaluates the primary vector function to render arrows or move particles, it passes these exact, pre-calculated results directly into your color function. The function must accept 4 or 5 parameters:
Should return a scalar or a NumPy array. Use vectorized NumPy operations for maximum efficiency. |
None
|
Example
Basic setup for a simple vector field defined by a mathematical function, with default coloring based on velocity magnitude and directly defined VectorMathEngine:
import FluxRender as fr
import numpy as np
# [Initializing the scene and coordinate system]
def my_field(x, y):
return np.sin(x), np.cos(y)
engine = fr.VectorMathEngine(primary_vector_function = my_field)
field = fr.VectorField(
vec_function = engine,
mode = fr.FieldMode.SCREEN_FIXED,
)
scene.add(field)
The same, but animated vector field and without directly defined VectorMathEngine (the engine will be created internally):
Source code in FluxRender/entities.py
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 | |
change_mode
Changes the rendering mode of a vector field and updates the related parameters accordingly, using default values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
new_mode
|
FieldMode
|
The new rendering mode to switch to. |
required |
Example
Source code in FluxRender/entities.py
evaluate_angle_vector
Evaluates the base reference angle vector at the specified spatial coordinates.
This method determines whether the reference angle vector is a static coordinate pair or a dynamically evaluated mathematical function. If it is a callable function, it safely executes it, automatically injecting the current time if the function signature requires it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float or ndarray
|
The x-coordinate(s) in the mathematical world space. |
required |
y
|
float or ndarray
|
The y-coordinate(s) in the mathematical world space. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
tuple
|
A tuple (component_x, component_y) representing the evaluated reference vector components. |
Notes
- Broadcasting: This method fully supports NumPy broadcasting. You can pass single
float values for pinpoint evaluation, or large multidimensional arrays (like those
generated by
numpy.meshgrid) to evaluate the entire mathematical space simultaneously.
Example
Evaluating a dynamically rotating reference angle at the origin:
import FluxRender as fr
import numpy as np
# [Initializing the scene and coordinate system]
def rotating_reference(x, y, t):
direction_x = np.cos(t)
direction_y = np.sin(t)
return direction_x, direction_y
field = fr.VectorField(
vec_function = lambda x, y: (y, -x),
color_property = fr.Property.ANGLE,
base_angle_vector = rotating_reference
)
scene.add(field)
# The engine automatically handles the underlying time injection
angle_vector_x, angle_vector_y = field.evaluate_angle_vector(0.0, 0.0)
print(f"Reference angle vector at the origin: ({angle_vector_x}, {angle_vector_y})")
Source code in FluxRender/entities.py
evaluate_scalar_function
Evaluates a user-provided mathematical scalar function, automatically handling time injection and vectorization.
This method serves as a robust adapter for custom user logic that maps spatial coordinates (and potentially
vector components) to a single scalar value. It analyzes the signature of the provided function to dynamically
inject the simulation time if required. It attempts to execute the function using native NumPy vectorization
for maximum performance, automatically falling back to numpy.vectorize if strictly scalar Python operations
are detected.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
user_defined_function
|
Callable
|
The custom scalar function or lambda to evaluate. |
required |
*spatial_arguments
|
The base spatial and/or vector arrays to pass into the function (e.g., evaluated_vector_x, evaluated_vector_y, world_x, world_y). |
()
|
Returns:
| Type | Description |
|---|---|
ndarray
|
numpy.ndarray: A single NumPy array containing the computed scalar values, properly sanitized and ready for rendering or further mathematical processing. |
Notes
- Time Injection: If
user_defined_functionaccepts exactly one parameter more than the number of provided*spatial_arguments, the current scene time is automatically injected during execution. - Vectorization Fallback: You do not need to write strictly vectorized NumPy code. Regular Python scalar operations will be caught and vectorized automatically, though writing native NumPy code is highly recommended for optimal rendering performance.
- Scalar Output: Unlike its vector counterpart, this method strictly expects the user's function to return a single value (or a single array) per spatial coordinate, not a tuple.
Example
Calculating and printing a custom physical metric (like kinetic energy) at specific points, while the field continues to render its default colors visually:
import FluxRender as fr
import numpy as np
# [Initializing the scene and coordinate system]
field = fr.VectorField(
vec_function = lambda x, y: (y, -x),
)
scene.add(field)
# Custom function that internally queries the field for vector data and calculates a scalar property (e.g., kinetic energy = 0.5 * (vx^2 + vy^2))
def calculate_kinetic_energy(x, y):
vector_dx, vector_dy = field.evaluate_vector_field(x, y)
kinetic_energy = 0.5 * (vector_dx**2 + vector_dy**2)
return kinetic_energy
# Define the exact spatial points we want to analyze
target_coordinates_x = np.array([0.0, 1.0, 2.0])
target_coordinates_y = np.array([0.0, 1.0, 2.0])
# Evaluate the custom metric across all points simultaneously
energy_results = field.evaluate_scalar_function(
calculate_kinetic_energy,
target_coordinates_x,
target_coordinates_y
)
print(f"Kinetic energy at points (0,0), (1,1) and (2,2): {energy_results}")
Source code in FluxRender/entities.py
evaluate_vector_field
Evaluates the primary vector field function at the specified spatial coordinates.
This method acts as a safe execution wrapper for the user-defined vector function. It delegates the execution to the internal evaluation handler, which manages potential numpy broadcasting issues, scalar fallbacks, and automatic time-parameter injection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float or ndarray
|
The x-coordinate(s) in the mathematical world space. |
required |
y
|
float or ndarray
|
The y-coordinate(s) in the mathematical world space. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
tuple
|
A tuple (vector_x, vector_y) representing the evaluated vector field components. |
Notes
- Broadcasting: This method fully supports NumPy broadcasting. You can pass single
float values for pinpoint evaluation, or large multidimensional arrays (like those
generated by
numpy.meshgrid) to evaluate the entire mathematical space simultaneously.
Example
Evaluating the field at a single focal point:
import FluxRender as fr
# [Initializing the scene and coordinate system]
field = fr.VectorField(
vec_function = lambda x, y: (y, -x),
color_property = fr.Property.VELOCITY
)
scene.add(field)
vector_component_x, vector_component_y = field.evaluate_vector_field(1.0, 0.0)
print(f"Vector field at (1.0, 0.0): ({vector_component_x}, {vector_component_y})")
# Result: (0.0, -1.0)
Evaluating the field at multiple points simultaneously using numpy arrays:
import numpy as np
# Define the exact spatial points we want to analyze
target_coordinates_x = np.array([0.0, 1.0, 2.0])
target_coordinates_y = np.array([0.0, 1.0, 2.0])
x_vectors, y_vectors = vec_field.evaluate_vector_field(
target_coordinates_x,
target_coordinates_y
)
print(f"Vector field at points (0,0), (1,1) and (2,2): [{x_vectors[0]}, {y_vectors[0]}] | [{x_vectors[1]}, {y_vectors[1]}] | [{x_vectors[2]}, {y_vectors[2]}]")
Source code in FluxRender/entities.py
evaluate_vector_function
Evaluates a user-provided mathematical function, automatically handling time injection and vectorization.
This method serves as a robust adapter for custom user logic. It analyzes the signature of the
provided function to dynamically inject the simulation time if required. Furthermore, it attempts
to execute the function using native NumPy vectorization for maximum performance. If the function
is strictly scalar (e.g., uses standard Python math modules instead of numpy), it automatically
falls back to numpy.vectorize to ensure compatibility across large coordinate grids.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
user_defined_function
|
Callable
|
The custom function or lambda to evaluate. |
required |
*spatial_arguments
|
The base spatial arrays to pass into the function (typically world_x, world_y). |
()
|
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
tuple
|
A tuple (evaluated_vector_x, evaluated_vector_y) containing the computed field components as sanitized NumPy arrays. |
Notes
- Time Injection: If
user_defined_functionaccepts exactly one parameter more than the number of provided*spatial_arguments(e.g., taking x, y, and t), the current scene time is automatically injected during execution. - Vectorization Fallback: You do not need to write strictly vectorized NumPy code. Regular Python scalar operations will be caught and vectorized automatically, though writing native NumPy code is highly recommended for optimal rendering performance.
Examples:
Evaluating a custom mathematical perturbation with automatic time injection:
import FluxRender as fr
import numpy as np
# [Initializing the scene and coordinate system]
field = fr.VectorField(
vec_function = lambda x, y: (y, -x),
)
scene.add(field)
# Notice the third parameter 't'. The engine detects this and injects it.
def custom_wind_perturbation(x, y, t):
perturbation_x = np.sin(x + t)
perturbation_y = np.cos(y + t)
return perturbation_x, perturbation_y
spatial_coordinates_x = np.array([0.0, 1.0, 2.0])
spatial_coordinates_y = np.array([0.0, 1.0, 2.0])
result_vectors_x, result_vectors_y = field.evaluate_vector_function(
custom_wind_perturbation,
spatial_coordinates_x,
spatial_coordinates_y
)
Source code in FluxRender/entities.py
update_configuration
This function refreshes a vector field.
Most often used when editing parameters not strictly related to the VectorField object (e.g., changing parameters in ColorMapper).
Example
If you change colors in ColorMapper:
my_color_mapper = ColorMapper()
# [Set up your vector field with my_color_mapper]
# a function called when you click a button that changes the color range in ColorMapper and updates the configuration in VectorField
def on_click():
my_color_mapper.max_hue = 180
my_color_mapper.min_hue = 240
my_vector_field.update_configuration()