@@ -36,13 +36,13 @@ jobs:
|
||||
pip install git+https://github.com/meadiode/cq_gears.git@main
|
||||
pip install -e "git+https://github.com/CadQuery/cadquery-plugins.git#egg=cq_cache&subdirectory=plugins/cq_cache"
|
||||
pip install git+https://github.com/gumyr/build123d.git#egg=build123d
|
||||
pip install git+https://github.com/JustinSDK/cqMore
|
||||
- name: Run build
|
||||
shell: bash --login {0}
|
||||
run: |
|
||||
micromamba info
|
||||
pyinstaller pyinstaller.spec ${{ github.event.inputs.type }}
|
||||
cp /home/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/pyinstaller/CQ-editor.sh /home/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/dist/
|
||||
rm /home/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/dist/CQ-editor/libstdc++.so.6
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: CQ-editor-Linux-x86_64
|
||||
@@ -73,6 +73,7 @@ jobs:
|
||||
pip install git+https://github.com/meadiode/cq_gears.git@main
|
||||
pip install -e "git+https://github.com/CadQuery/cadquery-plugins.git#egg=cq_cache&subdirectory=plugins/cq_cache"
|
||||
pip install git+https://github.com/gumyr/build123d.git#egg=build123d
|
||||
pip install git+https://github.com/JustinSDK/cqMore
|
||||
- name: Run build
|
||||
shell: bash --login {0}
|
||||
run: |
|
||||
@@ -107,6 +108,7 @@ jobs:
|
||||
pip install git+https://github.com/meadiode/cq_gears.git@main
|
||||
pip install -e "git+https://github.com/CadQuery/cadquery-plugins.git#egg=cq_cache&subdirectory=plugins/cq_cache"
|
||||
pip install git+https://github.com/gumyr/build123d.git#egg=build123d
|
||||
pip install git+https://github.com/JustinSDK/cqMore
|
||||
- name: Run build
|
||||
shell: powershell
|
||||
run: |
|
||||
|
||||
@@ -7,7 +7,7 @@ from types import SimpleNamespace
|
||||
|
||||
from OCP.XCAFPrs import XCAFPrs_AISObject
|
||||
from OCP.TopoDS import TopoDS_Shape
|
||||
from OCP.AIS import AIS_InteractiveObject, AIS_Shape, AIS_ColoredShape
|
||||
from OCP.AIS import AIS_InteractiveObject, AIS_Shape
|
||||
from OCP.Quantity import \
|
||||
Quantity_TOC_RGB as TOC_RGB, Quantity_Color
|
||||
|
||||
@@ -33,6 +33,10 @@ def to_compound(obj : Union[cq.Workplane, List[cq.Workplane], cq.Shape, List[cq.
|
||||
vals.append(cq.Shape.cast(obj))
|
||||
elif isinstance(obj,list) and isinstance(obj[0],TopoDS_Shape):
|
||||
vals.extend(cq.Shape.cast(o) for o in obj)
|
||||
elif hasattr(obj, "wrapped") and isinstance(obj.wrapped, TopoDS_Shape):
|
||||
vals.append(cq.Shape.cast(obj.wrapped))
|
||||
elif hasattr(obj, "_obj") and hasattr(obj._obj, "wrapped") and isinstance(obj._obj.wrapped, TopoDS_Shape):
|
||||
vals.append(cq.Shape.cast(obj._obj.wrapped))
|
||||
elif isinstance(obj, cq.Sketch):
|
||||
if obj._faces:
|
||||
vals.append(obj._faces)
|
||||
@@ -62,7 +66,7 @@ def make_AIS(obj : Union[cq.Workplane, List[cq.Workplane], cq.Shape, List[cq.Sha
|
||||
ais = obj
|
||||
else:
|
||||
shape = to_compound(obj)
|
||||
ais = AIS_ColoredShape(shape.wrapped)
|
||||
ais = AIS_Shape(shape.wrapped)
|
||||
|
||||
if 'alpha' in options:
|
||||
ais.SetTransparency(options['alpha'])
|
||||
@@ -105,13 +109,23 @@ def to_occ_color(color) -> Quantity_Color:
|
||||
color.blueF(),
|
||||
TOC_RGB)
|
||||
|
||||
def get_occ_color(ais : AIS_ColoredShape) -> QColor:
|
||||
|
||||
color = Quantity_Color()
|
||||
ais.Color(color)
|
||||
def get_occ_color(obj : Union[AIS_InteractiveObject, Quantity_Color]) -> QColor:
|
||||
|
||||
if isinstance(obj, AIS_InteractiveObject):
|
||||
color = Quantity_Color()
|
||||
obj.Color(color)
|
||||
else:
|
||||
color = obj
|
||||
|
||||
return QColor.fromRgbF(color.Red(), color.Green(), color.Blue())
|
||||
|
||||
def set_color(ais : AIS_Shape, color : Quantity_Color) -> AIS_Shape:
|
||||
|
||||
drawer = ais.Attributes()
|
||||
drawer.ShadingAspect().SetColor(color)
|
||||
|
||||
return ais
|
||||
|
||||
def reload_cq():
|
||||
|
||||
# NB: order of reloads is important
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
import cadquery as cq
|
||||
from cadquery.occ_impl.assembly import toCAF
|
||||
|
||||
from typing import List, Union
|
||||
from imp import reload
|
||||
from types import SimpleNamespace
|
||||
|
||||
from OCP.XCAFPrs import XCAFPrs_AISObject
|
||||
from OCP.TopoDS import TopoDS_Shape
|
||||
from OCP.AIS import AIS_InteractiveObject, AIS_Shape, AIS_ColoredShape
|
||||
from OCP.Quantity import \
|
||||
Quantity_TOC_RGB as TOC_RGB, Quantity_Color
|
||||
|
||||
from PyQt5.QtGui import QColor
|
||||
|
||||
def find_cq_objects(results : dict):
|
||||
|
||||
return {k:SimpleNamespace(shape=v,options={}) for k,v in results.items() if isinstance(v,cq.Workplane)}
|
||||
|
||||
def to_compound(obj : Union[cq.Workplane, List[cq.Workplane], cq.Shape, List[cq.Shape], cq.Sketch]):
|
||||
|
||||
vals = []
|
||||
|
||||
if isinstance(obj,cq.Workplane):
|
||||
vals.extend(obj.vals())
|
||||
elif isinstance(obj,cq.Shape):
|
||||
vals.append(obj)
|
||||
elif isinstance(obj,list) and isinstance(obj[0],cq.Workplane):
|
||||
for o in obj: vals.extend(o.vals())
|
||||
elif isinstance(obj,list) and isinstance(obj[0],cq.Shape):
|
||||
vals.extend(obj)
|
||||
elif isinstance(obj, TopoDS_Shape):
|
||||
vals.append(cq.Shape.cast(obj))
|
||||
elif isinstance(obj,list) and isinstance(obj[0],TopoDS_Shape):
|
||||
vals.extend(cq.Shape.cast(o) for o in obj)
|
||||
elif isinstance(obj, cq.Sketch):
|
||||
if obj._faces:
|
||||
vals.append(obj._faces)
|
||||
else:
|
||||
vals.extend(obj._edges)
|
||||
else:
|
||||
raise ValueError(f'Invalid type {type(obj)}')
|
||||
|
||||
return cq.Compound.makeCompound(vals)
|
||||
|
||||
def to_workplane(obj : cq.Shape):
|
||||
|
||||
rv = cq.Workplane('XY')
|
||||
rv.objects = [obj,]
|
||||
|
||||
return rv
|
||||
|
||||
def make_AIS(obj : Union[cq.Workplane, List[cq.Workplane], cq.Shape, List[cq.Shape], cq.Assembly, AIS_InteractiveObject],
|
||||
options={}):
|
||||
|
||||
shape = None
|
||||
|
||||
if isinstance(obj, cq.Assembly):
|
||||
label, shape = toCAF(obj)
|
||||
ais = XCAFPrs_AISObject(label)
|
||||
elif isinstance(obj, AIS_InteractiveObject):
|
||||
ais = obj
|
||||
else:
|
||||
shape = to_compound(obj)
|
||||
ais = AIS_ColoredShape(shape.wrapped)
|
||||
|
||||
if 'alpha' in options:
|
||||
ais.SetTransparency(options['alpha'])
|
||||
if 'color' in options:
|
||||
ais.SetColor(to_occ_color(options['color']))
|
||||
if 'rgba' in options:
|
||||
r,g,b,a = options['rgba']
|
||||
ais.SetColor(to_occ_color((r,g,b)))
|
||||
ais.SetTransparency(a)
|
||||
|
||||
return ais,shape
|
||||
|
||||
def export(obj : Union[cq.Workplane, List[cq.Workplane]], type : str,
|
||||
file, precision=1e-1):
|
||||
|
||||
comp = to_compound(obj)
|
||||
|
||||
if type == 'stl':
|
||||
comp.exportStl(file, tolerance=precision)
|
||||
elif type == 'step':
|
||||
comp.exportStep(file)
|
||||
elif type == 'brep':
|
||||
comp.exportBrep(file)
|
||||
|
||||
def to_occ_color(color) -> Quantity_Color:
|
||||
|
||||
if not isinstance(color, QColor):
|
||||
if isinstance(color, tuple):
|
||||
if isinstance(color[0], int):
|
||||
color = QColor(*color)
|
||||
elif isinstance(color[0], float):
|
||||
color = QColor.fromRgbF(*color)
|
||||
else:
|
||||
raise ValueError('Unknown color format')
|
||||
else:
|
||||
color = QColor(color)
|
||||
|
||||
return Quantity_Color(color.redF(),
|
||||
color.greenF(),
|
||||
color.blueF(),
|
||||
TOC_RGB)
|
||||
|
||||
def get_occ_color(ais : AIS_ColoredShape) -> QColor:
|
||||
|
||||
color = Quantity_Color()
|
||||
ais.Color(color)
|
||||
|
||||
return QColor.fromRgbF(color.Red(), color.Green(), color.Blue())
|
||||
|
||||
def reload_cq():
|
||||
|
||||
# NB: order of reloads is important
|
||||
reload(cq.types)
|
||||
reload(cq.occ_impl.geom)
|
||||
reload(cq.occ_impl.shapes)
|
||||
reload(cq.occ_impl.shapes)
|
||||
reload(cq.occ_impl.importers.dxf)
|
||||
reload(cq.occ_impl.importers)
|
||||
reload(cq.occ_impl.solver)
|
||||
reload(cq.occ_impl.assembly)
|
||||
reload(cq.occ_impl.sketch_solver)
|
||||
reload(cq.hull)
|
||||
reload(cq.selectors)
|
||||
reload(cq.sketch)
|
||||
reload(cq.occ_impl.exporters.svg)
|
||||
reload(cq.cq)
|
||||
reload(cq.occ_impl.exporters.utils)
|
||||
reload(cq.occ_impl.exporters.dxf)
|
||||
reload(cq.occ_impl.exporters.amf)
|
||||
reload(cq.occ_impl.exporters.json)
|
||||
#reload(cq.occ_impl.exporters.assembly)
|
||||
reload(cq.occ_impl.exporters)
|
||||
reload(cq.assembly)
|
||||
reload(cq)
|
||||
|
||||
|
||||
def is_obj_empty(obj : Union[cq.Workplane,cq.Shape]) -> bool:
|
||||
|
||||
rv = False
|
||||
|
||||
if isinstance(obj, cq.Workplane):
|
||||
rv = True if isinstance(obj.val(), cq.Vector) else False
|
||||
|
||||
return rv
|
||||
@@ -9,7 +9,8 @@ from OCP.gp import gp_Dir, gp_Pnt, gp_Ax1
|
||||
|
||||
from ..mixins import ComponentMixin
|
||||
from ..icons import icon
|
||||
from ..cq_utils import make_AIS, export, to_occ_color, is_obj_empty, get_occ_color
|
||||
from ..cq_utils import make_AIS, export, to_occ_color, is_obj_empty, get_occ_color, set_color
|
||||
from .viewer import DEFAULT_FACE_COLOR
|
||||
from ..utils import splitter, layout, get_save_filename
|
||||
|
||||
class TopTreeItem(QTreeWidgetItem):
|
||||
@@ -49,14 +50,19 @@ class ObjectTreeItem(QTreeWidgetItem):
|
||||
|
||||
self.properties['Name'] = name
|
||||
self.properties['Alpha'] = ais.Transparency()
|
||||
self.properties['Color'] = get_occ_color(ais) if ais else color
|
||||
self.properties['Color'] = get_occ_color(ais) if ais and ais.HasColor() else get_occ_color(DEFAULT_FACE_COLOR)
|
||||
self.properties.sigTreeStateChanged.connect(self.propertiesChanged)
|
||||
|
||||
def propertiesChanged(self,*args):
|
||||
def propertiesChanged(self, properties, changed):
|
||||
|
||||
changed_prop = changed[0][0]
|
||||
|
||||
self.setData(0,0,self.properties['Name'])
|
||||
self.ais.SetTransparency(self.properties['Alpha'])
|
||||
self.ais.SetColor(to_occ_color(self.properties['Color']))
|
||||
|
||||
if changed_prop.name() == 'Color':
|
||||
set_color(self.ais, to_occ_color(self.properties['Color']))
|
||||
|
||||
self.ais.Redisplay()
|
||||
|
||||
if self.properties['Visible']:
|
||||
|
||||
@@ -1,22 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from PyQt5.QtWidgets import QWidget, QDialog, QTreeWidgetItem, QApplication, QAction
|
||||
|
||||
from OCP.Graphic3d import Graphic3d_Camera, Graphic3d_StereoMode
|
||||
from PyQt5.QtWidgets import (QWidget, QPushButton, QDialog, QTreeWidget,
|
||||
QTreeWidgetItem, QVBoxLayout, QFileDialog,
|
||||
QHBoxLayout, QFrame, QLabel, QApplication,
|
||||
QToolBar, QAction)
|
||||
|
||||
from PyQt5.QtCore import QSize, pyqtSlot, pyqtSignal, QMetaObject, Qt
|
||||
from PyQt5.QtCore import pyqtSlot, pyqtSignal
|
||||
from PyQt5.QtGui import QIcon
|
||||
|
||||
from OCP.AIS import AIS_Shaded,AIS_WireFrame, AIS_ColoredShape, \
|
||||
AIS_Axis, AIS_Line
|
||||
from OCP.Aspect import Aspect_GDM_Lines, Aspect_GT_Rectangular, Aspect_GFM_VER
|
||||
from OCP.Quantity import Quantity_NOC_BLACK as BLACK, \
|
||||
from OCP.Graphic3d import Graphic3d_Camera, Graphic3d_StereoMode, Graphic3d_NOM_JADE,\
|
||||
Graphic3d_MaterialAspect
|
||||
from OCP.AIS import AIS_Shaded,AIS_WireFrame, AIS_ColoredShape, AIS_Axis
|
||||
from OCP.Aspect import Aspect_GDM_Lines, Aspect_GT_Rectangular
|
||||
from OCP.Quantity import Quantity_NOC_BLACK as BLACK, Quantity_NOC_GOLD as GOLD,\
|
||||
Quantity_TOC_RGB as TOC_RGB, Quantity_Color
|
||||
from OCP.Geom import Geom_CylindricalSurface, Geom_Plane, Geom_Circle,\
|
||||
Geom_TrimmedCurve, Geom_Axis1Placement, Geom_Axis2Placement, Geom_Line
|
||||
from OCP.gp import gp_Trsf, gp_Vec, gp_Ax3, gp_Dir, gp_Pnt, gp_Ax1
|
||||
from OCP.Geom import Geom_Axis1Placement
|
||||
from OCP.gp import gp_Ax3, gp_Dir, gp_Pnt, gp_Ax1
|
||||
|
||||
from ..utils import layout, get_save_filename
|
||||
from ..mixins import ComponentMixin
|
||||
@@ -27,7 +21,9 @@ from .occt_widget import OCCTWidget
|
||||
|
||||
from pyqtgraph.parametertree import Parameter
|
||||
import qtawesome as qta
|
||||
|
||||
DEFAULT_FACE_COLOR = Quantity_Color(GOLD)
|
||||
DEFAULT_EDGE_COLOR = Quantity_Color(BLACK)
|
||||
DEFAULT_EDGE_WIDTH = 2
|
||||
|
||||
class OCCViewer(QWidget,ComponentMixin):
|
||||
|
||||
@@ -64,9 +60,23 @@ class OCCViewer(QWidget,ComponentMixin):
|
||||
[self.canvas,],
|
||||
top_widget=self,
|
||||
margin=0)
|
||||
|
||||
self.setup_default_drawer() #misspelled in original
|
||||
self.updatePreferences()
|
||||
|
||||
def setup_default_drawer(self):
|
||||
|
||||
# set the default color and material
|
||||
material = Graphic3d_MaterialAspect(Graphic3d_NOM_JADE)
|
||||
|
||||
shading_aspect = self.canvas.context.DefaultDrawer().ShadingAspect()
|
||||
shading_aspect.SetMaterial(material)
|
||||
shading_aspect.SetColor(DEFAULT_FACE_COLOR)
|
||||
|
||||
# face edge lw
|
||||
line_aspect = self.canvas.context.DefaultDrawer().FaceBoundaryAspect()
|
||||
line_aspect.SetWidth(DEFAULT_EDGE_WIDTH)
|
||||
line_aspect.SetColor(DEFAULT_EDGE_COLOR)
|
||||
|
||||
def updatePreferences(self,*args):
|
||||
|
||||
color1 = to_occ_color(self.preferences['Background color'])
|
||||
|
||||
@@ -38,7 +38,7 @@ a = Analysis(['run.py'],
|
||||
'pyqtgraph.imageview.ImageViewTemplate_pyqt5', 'xmlrpc',
|
||||
'zmq.backend', 'cq_warehouse', 'cq_warehouse.bearing', 'cq_warehouse.chain',
|
||||
'cq_warehouse.drafting', 'cq_warehouse.extensions', 'cq_warehouse.fastener',
|
||||
'cq_warehouse.sprocket', 'cq_warehouse.thread', 'cq_gears', 'cq_cache', 'build123d'] + hiddenimports1 + hiddenimports2,
|
||||
'cq_warehouse.sprocket', 'cq_warehouse.thread', 'cq_gears', 'cq_cache', 'build123d', 'cqmore'] + hiddenimports1 + hiddenimports2,
|
||||
hookspath=[],
|
||||
runtime_hooks=['pyinstaller/pyi_rth_occ.py',
|
||||
'pyinstaller/pyi_rth_fontconfig.py'],
|
||||
|
||||
@@ -114,7 +114,7 @@ def get_rgba(ais):
|
||||
alpha = ais.Transparency()
|
||||
color = get_occ_color(ais)
|
||||
|
||||
return color.redF(),color.redF(),color.redF(),alpha
|
||||
return color.redF(), color.greenF(), color.blueF(), alpha
|
||||
|
||||
@pytest.fixture
|
||||
def main(qtbot,mocker):
|
||||
@@ -1017,15 +1017,14 @@ def test_render_colors(main_clean):
|
||||
CQ = obj_tree.CQ
|
||||
|
||||
# object 1 (defualt color)
|
||||
r,g,b,a = get_rgba(CQ.child(0).ais)
|
||||
assert( a == 0 )
|
||||
assert( r != 1.0 )
|
||||
assert not CQ.child(0).ais.HasColor()
|
||||
|
||||
# object 2
|
||||
r,g,b,a = get_rgba(CQ.child(1).ais)
|
||||
assert( a == 0.5 )
|
||||
assert( r == 1.0 )
|
||||
|
||||
assert( g == 0.0 )
|
||||
|
||||
# object 3
|
||||
r,g,b,a = get_rgba(CQ.child(2).ais)
|
||||
assert( a == 0.5)
|
||||
@@ -1059,20 +1058,11 @@ def test_render_colors_console(main_clean):
|
||||
console = win.components['console']
|
||||
|
||||
console.execute_command(code_color)
|
||||
|
||||
def get_rgba(ais):
|
||||
|
||||
alpha = ais.Transparency()
|
||||
color = get_occ_color(ais)
|
||||
|
||||
return color.redF(),color.redF(),color.redF(),alpha
|
||||
|
||||
|
||||
CQ = obj_tree.CQ
|
||||
|
||||
# object 1 (defualt color)
|
||||
r,g,b,a = get_rgba(CQ.child(0).ais)
|
||||
assert( a == 0 )
|
||||
assert( r != 1.0 )
|
||||
assert not CQ.child(0).ais.HasColor()
|
||||
|
||||
# object 2
|
||||
r,g,b,a = get_rgba(CQ.child(1).ais)
|
||||
|
||||
Reference in New Issue
Block a user