-
Notifications
You must be signed in to change notification settings - Fork 359
Support for materials #1815
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Support for materials #1815
Changes from all commits
e8f77f5
4967786
f2e22bc
c0691cb
15bcf4e
288f1e6
4bab75e
cded5e5
fbe56fc
4a0bc97
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,3 +38,6 @@ out1.3mf | |
out2.3mf | ||
out3.3mf | ||
orig.dxf | ||
box.brep | ||
sketch.dxf | ||
material_test* |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,296 @@ | ||
from dataclasses import dataclass | ||
from typing import Optional, Tuple, TypeAlias, overload | ||
|
||
from OCP.Quantity import Quantity_Color, Quantity_ColorRGBA, Quantity_TOC_sRGB | ||
from OCP.XCAFDoc import ( | ||
XCAFDoc_Material, | ||
XCAFDoc_VisMaterial, | ||
XCAFDoc_VisMaterialPBR, | ||
XCAFDoc_VisMaterialCommon, | ||
) | ||
from OCP.TCollection import TCollection_HAsciiString | ||
from vtkmodules.vtkRenderingCore import vtkActor | ||
from vtkmodules.vtkCommonColor import vtkNamedColors | ||
|
||
|
||
RGB: TypeAlias = Tuple[float, float, float] | ||
RGBA: TypeAlias = Tuple[float, float, float, float] | ||
|
||
|
||
@dataclass(frozen=True) | ||
class Color: | ||
""" | ||
Simple color representation with optional alpha channel. | ||
All values are in range [0.0, 1.0]. | ||
""" | ||
|
||
red: float | ||
green: float | ||
blue: float | ||
alpha: float = 1.0 | ||
|
||
@overload | ||
def __init__(self): | ||
""" | ||
Construct a Color with default value (white). | ||
""" | ||
... | ||
|
||
@overload | ||
def __init__(self, name: str): | ||
""" | ||
Construct a Color from a name. | ||
:param name: name of the color, e.g. green | ||
""" | ||
... | ||
|
||
@overload | ||
def __init__(self, red: float, green: float, blue: float, alpha: float = 1.0): | ||
""" | ||
Construct a Color from RGB(A) values. | ||
:param red: red value, 0-1 | ||
:param green: green value, 0-1 | ||
:param blue: blue value, 0-1 | ||
:param alpha: alpha value, 0-1 (default: 1.0) | ||
""" | ||
... | ||
|
||
def __init__(self, *args, **kwargs): | ||
# Check for unknown kwargs | ||
valid_kwargs = {"red", "green", "blue", "alpha", "name"} | ||
unknown_kwargs = set(kwargs.keys()) - valid_kwargs | ||
if unknown_kwargs: | ||
raise TypeError(f"Got unexpected keyword arguments: {unknown_kwargs}") | ||
|
||
number_of_args = len(args) + len(kwargs) | ||
if number_of_args == 0: | ||
# Handle no-args case (default yellow) | ||
r, g, b, a = 1.0, 1.0, 0.0, 1.0 | ||
elif (number_of_args == 1 and isinstance(args[0], str)) or "name" in kwargs: | ||
color_name = args[0] if number_of_args == 1 else kwargs["name"] | ||
|
||
# Try to get color from OCCT first, fall back to VTK if not found | ||
try: | ||
# Get color from OCCT | ||
occ_rgba = Quantity_ColorRGBA() | ||
exists = Quantity_ColorRGBA.ColorFromName_s(color_name, occ_rgba) | ||
if not exists: | ||
raise ValueError(f"Unknown color name: {color_name}") | ||
occ_rgb = occ_rgba.GetRGB() | ||
r, g, b, a = ( | ||
occ_rgb.Red(), | ||
occ_rgb.Green(), | ||
occ_rgb.Blue(), | ||
occ_rgba.Alpha(), | ||
) | ||
except ValueError: | ||
# Check if color exists in VTK | ||
vtk_colors = vtkNamedColors() | ||
if not vtk_colors.ColorExists(color_name): | ||
raise ValueError(f"Unsupported color name: {color_name}") | ||
|
||
# Get color from VTK | ||
vtk_rgba = vtk_colors.GetColor4d(color_name) | ||
r = vtk_rgba.GetRed() | ||
g = vtk_rgba.GetGreen() | ||
b = vtk_rgba.GetBlue() | ||
a = vtk_rgba.GetAlpha() | ||
|
||
elif number_of_args <= 4: | ||
r, g, b, a = args + (4 - len(args)) * (1.0,) | ||
|
||
if "red" in kwargs: | ||
r = kwargs["red"] | ||
if "green" in kwargs: | ||
g = kwargs["green"] | ||
if "blue" in kwargs: | ||
b = kwargs["blue"] | ||
if "alpha" in kwargs: | ||
a = kwargs["alpha"] | ||
|
||
elif number_of_args > 4: | ||
raise ValueError("Too many arguments") | ||
|
||
# Validate values | ||
for name, value in [("red", r), ("green", g), ("blue", b), ("alpha", a)]: | ||
if not 0.0 <= value <= 1.0: | ||
raise ValueError(f"{name} component must be between 0.0 and 1.0") | ||
|
||
# Set all attributes at once | ||
object.__setattr__(self, "red", r) | ||
object.__setattr__(self, "green", g) | ||
object.__setattr__(self, "blue", b) | ||
object.__setattr__(self, "alpha", a) | ||
|
||
def rgb(self) -> RGB: | ||
"""Get RGB components as tuple.""" | ||
return (self.red, self.green, self.blue) | ||
|
||
def rgba(self) -> RGBA: | ||
"""Get RGBA components as tuple.""" | ||
return (self.red, self.green, self.blue, self.alpha) | ||
|
||
def toTuple(self) -> RGBA: | ||
"""Get RGBA components as tuple.""" | ||
return self.rgba() | ||
|
||
def toQuantityColor(self) -> "Quantity_Color": | ||
"""Convert Color to a Quantity_Color object.""" | ||
|
||
return Quantity_Color(self.red, self.green, self.blue, Quantity_TOC_sRGB) | ||
|
||
def toQuantityColorRGBA(self) -> "Quantity_ColorRGBA": | ||
"""Convert Color to a Quantity_ColorRGBA object.""" | ||
rgb = self.toQuantityColor() | ||
return Quantity_ColorRGBA(rgb, self.alpha) | ||
|
||
def __repr__(self) -> str: | ||
"""String representation of the color.""" | ||
return f"Color(r={self.red}, g={self.green}, b={self.blue}, a={self.alpha})" | ||
|
||
def __str__(self) -> str: | ||
"""String representation of the color.""" | ||
return f"({self.red}, {self.green}, {self.blue}, {self.alpha})" | ||
|
||
|
||
@dataclass(unsafe_hash=True) | ||
class SimpleMaterial: | ||
""" | ||
Traditional material model matching OpenCascade's XCAFDoc_VisMaterialCommon. | ||
""" | ||
|
||
ambient_color: Color | ||
diffuse_color: Color | ||
specular_color: Color | ||
shininess: float | ||
transparency: float | ||
|
||
def __post_init__(self): | ||
"""Validate the material properties.""" | ||
# Validate ranges | ||
if not 0.0 <= self.shininess <= 1.0: | ||
raise ValueError("Shininess must be between 0.0 and 1.0") | ||
if not 0.0 <= self.transparency <= 1.0: | ||
raise ValueError("Transparency must be between 0.0 and 1.0") | ||
|
||
def applyToVTKActor(self, actor: "vtkActor") -> None: | ||
"""Apply common material properties to a VTK actor.""" | ||
prop = actor.GetProperty() | ||
prop.SetInterpolationToPhong() | ||
prop.SetAmbientColor(*self.ambient_color.rgb()) | ||
prop.SetDiffuseColor(*self.diffuse_color.rgb()) | ||
prop.SetSpecularColor(*self.specular_color.rgb()) | ||
prop.SetSpecular(self.shininess) | ||
prop.SetOpacity(1.0 - self.transparency) | ||
|
||
|
||
@dataclass(unsafe_hash=True) | ||
class PbrMaterial: | ||
""" | ||
PBR material definition matching OpenCascade's XCAFDoc_VisMaterialPBR. | ||
Note: Emission support will be added in a future version with proper texture support. | ||
""" | ||
|
||
# Base color and texture | ||
base_color: Color | ||
metallic: float | ||
roughness: float | ||
refraction_index: float | ||
|
||
def __post_init__(self): | ||
"""Validate the material properties.""" | ||
# Validate ranges | ||
if not 0.0 <= self.metallic <= 1.0: | ||
raise ValueError("Metallic must be between 0.0 and 1.0") | ||
if not 0.0 <= self.roughness <= 1.0: | ||
raise ValueError("Roughness must be between 0.0 and 1.0") | ||
if not 1.0 <= self.refraction_index <= 3.0: | ||
raise ValueError("Refraction index must be between 1.0 and 3.0") | ||
|
||
def applyToVtkActor(self, actor: "vtkActor") -> None: | ||
"""Apply PBR material properties to a VTK actor.""" | ||
prop = actor.GetProperty() | ||
prop.SetInterpolationToPBR() | ||
prop.SetColor(*self.base_color.rgb()) | ||
prop.SetOpacity(self.base_color.alpha) | ||
prop.SetMetallic(self.metallic) | ||
prop.SetRoughness(self.roughness) | ||
prop.SetBaseIOR(self.refraction_index) | ||
|
||
|
||
@dataclass(unsafe_hash=True) | ||
class Material: | ||
""" | ||
Material class that can store multiple representation types simultaneously. | ||
Different exporters/viewers can use the most appropriate representation. | ||
""" | ||
|
||
name: str | ||
description: str | ||
density: float | ||
density_unit: str = "kg/m³" | ||
|
||
# Material representations | ||
color: Optional[Color] = None | ||
simple: Optional[SimpleMaterial] = None | ||
pbr: Optional[PbrMaterial] = None | ||
|
||
def __post_init__(self): | ||
"""Validate that at least one representation is provided.""" | ||
if not any([self.color, self.simple, self.pbr]): | ||
raise ValueError("Material must have at least one representation defined") | ||
|
||
def applyToVtkActor(self, actor: "vtkActor") -> None: | ||
"""Apply material properties to a VTK actor.""" | ||
prop = actor.GetProperty() | ||
prop.SetMaterialName(self.name) | ||
|
||
if self.pbr: | ||
self.pbr.applyToVtkActor(actor) | ||
elif self.simple: | ||
self.simple.applyToVTKActor(actor) | ||
elif self.color: | ||
r, g, b, a = self.color.toTuple() | ||
prop.SetColor(r, g, b) | ||
prop.SetOpacity(a) | ||
|
||
def toXCAFDocMaterial(self) -> "XCAFDoc_Material": | ||
"""Convert to OCCT material object.""" | ||
|
||
occt_material = XCAFDoc_Material() | ||
occt_material.Set( | ||
TCollection_HAsciiString(self.name), | ||
TCollection_HAsciiString(self.description), | ||
self.density, | ||
TCollection_HAsciiString(self.density_unit), | ||
TCollection_HAsciiString("DENSITY"), | ||
) | ||
return occt_material | ||
|
||
def toXCAFDocVisMaterial(self) -> "XCAFDoc_VisMaterial": | ||
"""Convert to OCCT visualization material object.""" | ||
vis_mat = XCAFDoc_VisMaterial() | ||
|
||
# Set up PBR material if provided | ||
if self.pbr: | ||
pbr_mat = XCAFDoc_VisMaterialPBR() | ||
pbr_mat.BaseColor = self.pbr.base_color.toQuantityColorRGBA() | ||
pbr_mat.Metallic = self.pbr.metallic | ||
pbr_mat.Roughness = self.pbr.roughness | ||
pbr_mat.RefractionIndex = self.pbr.refraction_index | ||
vis_mat.SetPbrMaterial(pbr_mat) | ||
|
||
# Set up common material if provided | ||
if self.simple: | ||
common_mat = XCAFDoc_VisMaterialCommon() | ||
common_mat.AmbientColor = self.simple.ambient_color.toQuantityColor() | ||
common_mat.DiffuseColor = self.simple.diffuse_color.toQuantityColor() | ||
common_mat.SpecularColor = self.simple.specular_color.toQuantityColor() | ||
common_mat.Shininess = self.simple.shininess | ||
common_mat.Transparency = self.simple.transparency | ||
vis_mat.SetCommonMaterial(common_mat) | ||
|
||
return vis_mat |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import cadquery as cq | ||
|
||
# Create a simple cube | ||
cube = cq.Workplane().box(10, 10, 10) | ||
|
||
# Define different materials | ||
# 1. Simple color material | ||
red_material = cq.Material( | ||
name="Red Plastic", | ||
description="A simple red plastic material", | ||
density=1200, # kg/m³ | ||
color=cq.Color(1.0, 0.0, 0.0, 1.0), # Red with full opacity | ||
) | ||
|
||
# 2. Common (legacy) material with traditional properties | ||
metal_material = cq.Material( | ||
name="Polished Steel", | ||
description="A shiny metallic material", | ||
density=7850, # kg/m³ | ||
simple=cq.SimpleMaterial( | ||
ambient_color=cq.Color(0.2, 0.2, 0.2, 1.0), | ||
diffuse_color=cq.Color(0.5, 0.5, 0.5, 1.0), | ||
specular_color=cq.Color(0.8, 0.8, 0.8, 1.0), | ||
shininess=0.8, # High shininess for metallic look | ||
transparency=0.0, | ||
), | ||
) | ||
|
||
# 3. PBR material with modern properties | ||
glass_material = cq.Material( | ||
name="Clear Glass", | ||
description="A transparent glass material", | ||
density=2500, # kg/m³ | ||
pbr=cq.PbrMaterial( | ||
base_color=cq.Color(0.9, 0.9, 0.9, 0.3), # Light gray with transparency | ||
metallic=0.0, # Non-metallic | ||
roughness=0.1, # Very smooth | ||
refraction_index=1.5, # Typical glass refractive index | ||
), | ||
) | ||
|
||
# 4. Combined material with both common and PBR properties | ||
gold_material = cq.Material( | ||
name="Gold", | ||
description="A golden material with both traditional and PBR properties", | ||
density=19300, # kg/m³ | ||
simple=cq.SimpleMaterial( | ||
ambient_color=cq.Color(0.2, 0.2, 0.0, 1.0), | ||
diffuse_color=cq.Color(0.8, 0.8, 0.0, 1.0), | ||
specular_color=cq.Color(1.0, 1.0, 0.0, 1.0), | ||
shininess=0.9, | ||
transparency=0.0, | ||
), | ||
pbr=cq.PbrMaterial( | ||
base_color=cq.Color(1.0, 0.8, 0.0, 1.0), # Gold color | ||
metallic=1.0, # Fully metallic | ||
roughness=0.2, # Slightly rough | ||
refraction_index=1.0, # Minimum valid refractive index for metals | ||
), | ||
) | ||
|
||
# Create an assembly with different materials | ||
assy = cq.Assembly() | ||
assy.add(cube, name="red_cube", material=red_material) | ||
assy.add(cube.translate((15, 0, 0)), name="metal_cube", material=metal_material) | ||
assy.add(cube.translate((30, 0, 0)), name="glass_cube", material=glass_material) | ||
assy.add(cube.translate((45, 0, 0)), name="gold_cube", material=gold_material) | ||
|
||
|
||
# Show the assembly in the UI | ||
show_object(assy) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
""" | ||
Example 028 - VTK Visualization with Materials and Environment Mapping | ||
This example demonstrates how to: | ||
1. Create 3D objects with different materials (simple color, common material, PBR material) | ||
2. Set up a VTK visualization with environment mapping | ||
3. Use HDR textures for realistic lighting and reflections | ||
4. Configure camera and rendering settings | ||
The example creates three objects: | ||
- A red box with a simple color material | ||
- A gold cylinder with common material properties (ambient, diffuse, specular) | ||
- A chrome sphere with PBR (Physically Based Rendering) material properties | ||
The scene is rendered with an HDR environment map that provides realistic lighting | ||
and reflections on the materials. | ||
Note: Emission support will be added in a future version with proper texture support. | ||
""" | ||
|
||
from pathlib import Path | ||
from cadquery.occ_impl.assembly import toVTK | ||
from vtkmodules.vtkRenderingCore import ( | ||
vtkRenderWindow, | ||
vtkRenderWindowInteractor, | ||
vtkTexture, | ||
) | ||
from vtkmodules.vtkIOImage import vtkHDRReader | ||
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleTrackballCamera | ||
from vtkmodules.vtkRenderingOpenGL2 import vtkOpenGLSkybox | ||
import cadquery as cq | ||
|
||
|
||
# Create basic shapes for our example | ||
red_box = cq.Workplane().box(10, 10, 10) # Create a 10x10x10 box | ||
gold_cylinder = cq.Workplane().cylinder( | ||
20, 5 | ||
) # Create a cylinder with radius 5 and height 20 | ||
chrome_sphere = cq.Workplane().sphere(8) # Create a sphere with radius 8 | ||
|
||
# Create a hexagonal prism | ||
glass_hex = ( | ||
cq.Workplane("XY") | ||
.polygon(6, 15) # Create a hexagon with radius 15 | ||
.extrude(10) # Extrude 10 units in Z direction | ||
) | ||
|
||
# Create an assembly to hold our objects | ||
assy = cq.Assembly(name="material_test") | ||
|
||
# Add a red box with a simple color material | ||
# This demonstrates the most basic material type | ||
assy.add( | ||
red_box, | ||
name="red_box", | ||
loc=cq.Location((-60, 0, 0)), # Position the box to the left | ||
material=cq.Material( | ||
name="Red", | ||
description="Simple red material", | ||
density=1000.0, | ||
color=cq.Color(1, 0, 0, 1), # Pure red with full opacity | ||
), | ||
) | ||
|
||
# Add a gold cylinder with common material properties | ||
# This demonstrates traditional material properties (ambient, diffuse, specular) | ||
assy.add( | ||
gold_cylinder, | ||
name="gold_cylinder", | ||
loc=cq.Location((-20, 0, 0)), # Position the cylinder to the left of center | ||
material=cq.Material( | ||
name="Gold", | ||
description="Metallic gold material", | ||
density=19320.0, # Actual density of gold in kg/m³ | ||
simple=cq.SimpleMaterial( | ||
ambient_color=cq.Color(0.24, 0.2, 0.07), # Dark gold ambient color | ||
diffuse_color=cq.Color(0.75, 0.6, 0.22), # Gold diffuse color | ||
specular_color=cq.Color(0.63, 0.56, 0.37), # Light gold specular color | ||
shininess=0.8, # High shininess for metallic look | ||
transparency=0.0, # Fully opaque | ||
), | ||
), | ||
) | ||
|
||
# Add a chrome sphere with PBR material properties | ||
# This demonstrates modern physically based rendering materials | ||
assy.add( | ||
chrome_sphere, | ||
name="chrome_sphere", | ||
loc=cq.Location((20, 0, 0)), # Position the sphere to the right of center | ||
material=cq.Material( | ||
name="Chrome", | ||
description="Polished chrome material", | ||
density=7190.0, # Density of chrome in kg/m³ | ||
pbr=cq.PbrMaterial( | ||
base_color=cq.Color(0.8, 0.8, 0.8), # Light gray base color | ||
metallic=1.0, # Fully metallic | ||
roughness=0.1, # Very smooth surface | ||
refraction_index=2.4, # High refraction index for chrome | ||
), | ||
), | ||
) | ||
|
||
# Add a glass hexagonal prism with PBR material properties | ||
# This demonstrates transparent materials with PBR | ||
assy.add( | ||
glass_hex, | ||
name="glass_hex", | ||
loc=cq.Location((60, 0, 0)), # Position the hexagon to the right | ||
material=cq.Material( | ||
name="Glass", | ||
description="Clear glass material", | ||
density=2500.0, # Density of glass in kg/m³ | ||
pbr=cq.PbrMaterial( | ||
base_color=cq.Color(0.9, 0.9, 0.9, 0.1), # Light gray with transparency | ||
metallic=0, # Non-metallic | ||
roughness=0.1, # Smooth surface | ||
refraction_index=2, # Typical glass refraction index | ||
), | ||
), | ||
) | ||
|
||
|
||
# Convert the assembly to VTK format for visualization | ||
renderer = toVTK(assy, edges=False) | ||
|
||
# Set up the render window | ||
render_window = vtkRenderWindow() | ||
render_window.SetSize(1920, 1080) # Set to Full HD resolution | ||
render_window.AddRenderer(renderer) | ||
|
||
# Load the HDR texture for environment mapping | ||
reader = vtkHDRReader() | ||
reader.SetFileName(Path(__file__).parent / "golden_gate_hills_1k.hdr") | ||
reader.Update() | ||
|
||
# Create and configure the texture | ||
texture = vtkTexture() | ||
texture.SetColorModeToDirectScalars() # Use HDR values directly | ||
texture.SetInputConnection(reader.GetOutputPort()) | ||
texture.MipmapOn() # Enable mipmapping for better quality | ||
texture.InterpolateOn() # Enable texture interpolation | ||
texture.SetRepeat(False) # Prevent texture repetition | ||
texture.SetEdgeClamp(True) # Clamp texture edges | ||
|
||
# Create a skybox using the HDR texture | ||
skybox = vtkOpenGLSkybox() | ||
skybox.SetTexture(texture) | ||
skybox.SetProjectionToCube() # Use cube map projection | ||
renderer.AddActor(skybox) | ||
|
||
# Set up PBR environment lighting | ||
renderer.UseImageBasedLightingOn() # Enable image-based lighting | ||
renderer.SetEnvironmentTexture(texture) # Use HDR texture for lighting | ||
renderer.UseSphericalHarmonicsOn() # Use spherical harmonics for better performance | ||
|
||
# Set up the interactor for user interaction | ||
interactor = vtkRenderWindowInteractor() | ||
interactor.SetRenderWindow(render_window) | ||
|
||
# Configure the renderer and camera | ||
renderer = render_window.GetRenderers().GetFirstRenderer() | ||
renderer.SetBackground(0.2, 0.3, 0.4) # Set dark blue-gray background | ||
camera = renderer.GetActiveCamera() | ||
camera.SetPosition(0, -10, 200) # Position camera above the scene | ||
camera.SetFocalPoint(0, 0, 0) # Look at the center of the scene | ||
camera.SetViewUp(0, 1, 0) # Set Y axis as up to see horizon | ||
camera.SetViewAngle(30) # Set field of view | ||
|
||
# Set up trackball camera interaction style | ||
interactor_style = vtkInteractorStyleTrackballCamera() | ||
interactor.SetInteractorStyle(interactor_style) | ||
|
||
if __name__ == "__main__": | ||
# Start the visualization | ||
interactor.Initialize() | ||
interactor.Start() |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -537,29 +537,6 @@ def solve_result_check(solve_result: dict) -> bool: | |||
return all(checks) | ||||
|
||||
|
||||
def test_color(): | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you need to remove a test, something is really wrong with the PR. I think you made to many backward incompatible changes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The test was not removed, just moved here: cadquery/tests/test_materials.py Line 106 in 4bab75e
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please revert the removal. |
||||
|
||||
c1 = cq.Color("red") | ||||
assert c1.wrapped.GetRGB().Red() == 1 | ||||
assert c1.wrapped.Alpha() == 1 | ||||
|
||||
c2 = cq.Color(1, 0, 0) | ||||
assert c2.wrapped.GetRGB().Red() == 1 | ||||
assert c2.wrapped.Alpha() == 1 | ||||
|
||||
c3 = cq.Color(1, 0, 0, 0.5) | ||||
assert c3.wrapped.GetRGB().Red() == 1 | ||||
assert c3.wrapped.Alpha() == 0.5 | ||||
|
||||
c4 = cq.Color() | ||||
|
||||
with pytest.raises(ValueError): | ||||
cq.Color("?????") | ||||
|
||||
with pytest.raises(ValueError): | ||||
cq.Color(1, 2, 3, 4, 5) | ||||
|
||||
|
||||
def test_assembly(simple_assy, nested_assy): | ||||
|
||||
# basic checks | ||||
|
Large diffs are not rendered by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather have the the original Color class not removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new Color class has the same behaviour as the old one (except toTuple, I will bring that back as alias for
rgba()
). I think it makes sense to unify color handling throughout the codebase instead of mixingColor
,str
, andtuple
(with 3 or 4 floats). As I touched every place where colors come up, and need them inside materials, it seemed obvious to me to update it (but you're right, backwards compatibility in the vtk functions is partially broken).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd propose to go back to the original class. Maybe also move the materials to the assy module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the rationale behind that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minimize the impact of the PR. For the second point, the organization of your module does not follow what is in general happening in the codebase. At least it should go to
occ_impl