mirror of
https://github.com/yeicor-3d/yet-another-cad-viewer.git
synced 2025-12-20 06:27:04 +01:00
Compare commits
114 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
437e8eb4ad | ||
|
|
7051a71710 | ||
|
|
28282f4b06 | ||
|
|
7f43367459 | ||
|
|
ba64f70300 | ||
|
|
05963d58f2 | ||
|
|
405c061f93 | ||
|
|
e0a00b2d32 | ||
|
|
90f4611ee8 | ||
|
|
ee954622bb | ||
|
|
f5be0618ad | ||
|
|
f92701a969 | ||
|
|
949f92a28f | ||
|
|
7618581ef5 | ||
|
|
5460d19fdb | ||
|
|
f84292e4b7 | ||
|
|
b597223228 | ||
|
|
8ec9a3f507 | ||
|
|
0ec339283e | ||
|
|
1d50dc20ba | ||
|
|
35331746b1 | ||
|
|
287f76c0ad | ||
|
|
dadb2b7a39 | ||
|
|
722432dfb0 | ||
|
|
a9184b224f | ||
|
|
3c732d7c85 | ||
|
|
d8fa1f1e0b | ||
|
|
1b03699677 | ||
|
|
7f6f777b47 | ||
|
|
68fb3b1a67 | ||
|
|
cd4a1d523b | ||
|
|
84cd6ba710 | ||
|
|
aa8492cd3d | ||
|
|
6f8710bd7a | ||
|
|
8b175b369a | ||
|
|
0be05967ca | ||
|
|
51f6165290 | ||
|
|
f147c83604 | ||
|
|
881de107c7 | ||
|
|
6b533dfbe1 | ||
|
|
2e3fb8beae | ||
|
|
e8baf5cd52 | ||
|
|
6c0289208f | ||
|
|
496f90fb56 | ||
|
|
696333e105 | ||
|
|
099a7aa972 | ||
|
|
b2aa568eb2 | ||
|
|
e685c8adcf | ||
|
|
19ddb670db | ||
|
|
8f1cd3e203 | ||
|
|
6b0fcd743f | ||
|
|
1d275936a4 | ||
|
|
f7c28a42c0 | ||
|
|
fa54829328 | ||
|
|
c8a7a3ac67 | ||
|
|
791b2608c5 | ||
|
|
ba8e40bc48 | ||
|
|
712626e791 | ||
|
|
734387a866 | ||
|
|
0988db9269 | ||
|
|
97d620b982 | ||
|
|
857d0a602f | ||
|
|
23f8aa8bdd | ||
|
|
03a04bd3fd | ||
|
|
57f91d046f | ||
|
|
758bc9b874 | ||
|
|
490a86796c | ||
|
|
f44270d913 | ||
|
|
4eed1b063e | ||
|
|
e3fe562d53 | ||
|
|
84ba81a5e5 | ||
|
|
d469f5da40 | ||
|
|
98e8de75dd | ||
|
|
e8d7985dba | ||
|
|
6aa680bf43 | ||
|
|
b629f07f5e | ||
|
|
9e4f571808 | ||
|
|
eaad9f3774 | ||
|
|
79f6359af1 | ||
|
|
ca5e9e03ab | ||
|
|
2ebdee2d42 | ||
|
|
c1773fb156 | ||
|
|
e05cc70f3a | ||
|
|
7d97ed5e93 | ||
|
|
823ee5462f | ||
|
|
64aebb5cf7 | ||
|
|
979713bb48 | ||
|
|
3b8efd628c | ||
|
|
f91033ef3d | ||
|
|
0f881a6de5 | ||
|
|
fe919f539e | ||
|
|
0b2efb006c | ||
|
|
7584af683e | ||
|
|
64358469ae | ||
|
|
28ad995982 | ||
|
|
3efb47fef1 | ||
|
|
1ca655f2f4 | ||
|
|
4fd6fc6e23 | ||
|
|
b6d21e7ef1 | ||
|
|
fb484b61da | ||
|
|
1ebfa3dd3f | ||
|
|
35bfb8679a | ||
|
|
dce407ca2b | ||
|
|
f9e90bee25 | ||
|
|
ea44096200 | ||
|
|
f3d19911c7 | ||
|
|
2214a4812c | ||
|
|
8b08afc1ea | ||
|
|
4d77723fe6 | ||
|
|
bd0364fcea | ||
|
|
3b466c0291 | ||
|
|
ade6faa6a3 | ||
|
|
c88959cc11 | ||
|
|
1e7fe81a60 |
8
.github/renovate.json5
vendored
8
.github/renovate.json5
vendored
@@ -6,13 +6,9 @@
|
||||
],
|
||||
"automerge": true,
|
||||
"automergeType": "branch",
|
||||
"schedule": [
|
||||
"before 3am on Saturday"
|
||||
],
|
||||
"schedule": [ "* * * * 0,6" ],
|
||||
"lockFileMaintenance": {
|
||||
"enabled": true,
|
||||
"schedule": [
|
||||
"before 3am on Saturday"
|
||||
]
|
||||
"schedule": [ "* * * * 0,6" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -981,7 +981,7 @@ third-party archives.
|
||||
|
||||
The following npm package may be included in this product:
|
||||
|
||||
- typescript@5.7.2
|
||||
- typescript@5.8.3
|
||||
|
||||
This package contains the following license:
|
||||
|
||||
@@ -1121,7 +1121,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The following npm package may be included in this product:
|
||||
|
||||
- @lit-labs/ssr-dom-shim@1.2.1
|
||||
- @lit-labs/ssr-dom-shim@1.3.0
|
||||
|
||||
This package contains the following license:
|
||||
|
||||
@@ -1247,7 +1247,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
The following npm package may be included in this product:
|
||||
|
||||
- @babel/parser@7.26.3
|
||||
- @babel/parser@7.27.0
|
||||
|
||||
This package contains the following license:
|
||||
|
||||
@@ -1420,7 +1420,7 @@ The following npm packages may be included in this product:
|
||||
|
||||
- @babel/helper-string-parser@7.25.9
|
||||
- @babel/helper-validator-identifier@7.25.9
|
||||
- @babel/types@7.26.3
|
||||
- @babel/types@7.27.0
|
||||
|
||||
These packages each contain the following license:
|
||||
|
||||
@@ -1451,7 +1451,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
The following npm package may be included in this product:
|
||||
|
||||
- three-mesh-bvh@0.8.3
|
||||
- three-mesh-bvh@0.9.0
|
||||
|
||||
This package contains the following license:
|
||||
|
||||
@@ -1601,7 +1601,7 @@ The MIT license applies to all non-font and non-icon files.
|
||||
|
||||
The following npm package may be included in this product:
|
||||
|
||||
- semver@7.6.3
|
||||
- semver@7.7.1
|
||||
|
||||
This package contains the following license:
|
||||
|
||||
@@ -1685,13 +1685,13 @@ THE SOFTWARE.
|
||||
|
||||
The following npm package may be included in this product:
|
||||
|
||||
- three@0.171.0
|
||||
- three@0.175.0
|
||||
|
||||
This package contains the following license:
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright © 2010-2024 three.js authors
|
||||
Copyright © 2010-2025 three.js authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -1775,7 +1775,7 @@ THE SOFTWARE.
|
||||
|
||||
The following npm package may be included in this product:
|
||||
|
||||
- vuetify@3.7.6
|
||||
- vuetify@3.8.0
|
||||
|
||||
This package contains the following license:
|
||||
|
||||
@@ -1844,7 +1844,7 @@ THE SOFTWARE.
|
||||
|
||||
The following npm package may be included in this product:
|
||||
|
||||
- ktx-parse@0.7.1
|
||||
- ktx-parse@1.0.0
|
||||
|
||||
This package contains the following license:
|
||||
|
||||
@@ -1906,9 +1906,9 @@ SOFTWARE.
|
||||
|
||||
The following npm packages may be included in this product:
|
||||
|
||||
- @gltf-transform/core@4.1.1
|
||||
- @gltf-transform/extensions@4.1.1
|
||||
- @gltf-transform/functions@4.1.1
|
||||
- @gltf-transform/core@4.1.3
|
||||
- @gltf-transform/extensions@4.1.3
|
||||
- @gltf-transform/functions@4.1.3
|
||||
|
||||
These packages each contain the following license:
|
||||
|
||||
@@ -1968,7 +1968,7 @@ THE SOFTWARE.
|
||||
|
||||
The following npm package may be included in this product:
|
||||
|
||||
- postcss@8.4.49
|
||||
- postcss@8.5.3
|
||||
|
||||
This package contains the following license:
|
||||
|
||||
@@ -1997,7 +1997,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
The following npm package may be included in this product:
|
||||
|
||||
- nanoid@3.3.8
|
||||
- nanoid@3.3.11
|
||||
|
||||
This package contains the following license:
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ const emit = defineEmits<{ remove: [string] }>()
|
||||
|
||||
let {sceneDocument} = inject<{ sceneDocument: Ref<Document> }>('sceneDocument')!!;
|
||||
|
||||
let expandedNames = ref<Array<string>>([]);
|
||||
const expandedNames = ref<Array<string>>([]);
|
||||
|
||||
function meshesList(sceneDocument: Document): Array<Array<Mesh>> {
|
||||
// Grouped by shared name
|
||||
@@ -44,7 +44,7 @@ defineExpose({findModel})
|
||||
|
||||
<template>
|
||||
<v-expansion-panels v-for="meshes in meshesList(sceneDocument)" :key="meshName(meshes[0])"
|
||||
v-model="expandedNames" multiple>
|
||||
v-model="expandedNames as any" multiple>
|
||||
<model :meshes="meshes" :viewer="props.viewer" @remove="onRemove(meshes[0])"/>
|
||||
</v-expansion-panels>
|
||||
</template>
|
||||
@@ -61,4 +61,4 @@ defineExpose({findModel})
|
||||
.v-overlay--active > .v-overlay__content {
|
||||
display: block !important; /* HACK: Fix buggy tooltips not showing? */
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
20
package.json
20
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "yet-another-cad-viewer",
|
||||
"version": "0.9.4",
|
||||
"version": "0.9.6",
|
||||
"description": "",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
@@ -22,7 +22,7 @@
|
||||
"@jamescoyle/vue-icon": "^0.1.2",
|
||||
"@mdi/js": "^7.4.47",
|
||||
"@mdi/svg": "^7.4.47",
|
||||
"three": "^0.173.0",
|
||||
"three": "^0.177.0",
|
||||
"three-mesh-bvh": "^0.9.0",
|
||||
"three-orientation-gizmo": "https://github.com/jrj2211/three-orientation-gizmo",
|
||||
"vue": "^3.5.13",
|
||||
@@ -31,17 +31,17 @@
|
||||
"devDependencies": {
|
||||
"@tsconfig/node20": "^20.1.4",
|
||||
"@types/node": "^22.9.3",
|
||||
"@types/three": "^0.173.0",
|
||||
"@vitejs/plugin-vue": "^5.2.0",
|
||||
"@vitejs/plugin-vue-jsx": "^4.1.0",
|
||||
"@types/three": "^0.177.0",
|
||||
"@vitejs/plugin-vue": "^6.0.0",
|
||||
"@vitejs/plugin-vue-jsx": "^5.0.0",
|
||||
"@vue/tsconfig": "^0.7.0",
|
||||
"buffer": "^5.5.0||^6.0.0",
|
||||
"commander": "^13.0.0",
|
||||
"generate-license-file": "^3.6.0",
|
||||
"npm-run-all2": "^7.0.1",
|
||||
"commander": "^14.0.0",
|
||||
"generate-license-file": "^4.0.0",
|
||||
"npm-run-all2": "^8.0.0",
|
||||
"terser": "^5.36.0",
|
||||
"typescript": "~5.7.0",
|
||||
"vite": "^6.0.0",
|
||||
"typescript": "~5.8.0",
|
||||
"vite": "^7.0.0",
|
||||
"vue-tsc": "^2.1.10"
|
||||
}
|
||||
}
|
||||
|
||||
832
poetry.lock
generated
832
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "yacv-server"
|
||||
version = "0.9.4"
|
||||
version = "0.9.6"
|
||||
description = "Yet Another CAD Viewer (server)"
|
||||
authors = ["Yeicor <4929005+Yeicor@users.noreply.github.com>"]
|
||||
license = "MIT"
|
||||
|
||||
@@ -10,7 +10,7 @@ from OCP.TopExp import TopExp
|
||||
from OCP.TopLoc import TopLoc_Location
|
||||
from OCP.TopTools import TopTools_IndexedMapOfShape
|
||||
from OCP.TopoDS import TopoDS_Shape
|
||||
from build123d import Compound, Shape, Color
|
||||
from build123d import Compound, Color
|
||||
|
||||
from yacv_server.gltf import GLTFMgr
|
||||
|
||||
@@ -78,7 +78,7 @@ def get_shape(obj: CADLike, error: bool = True) -> Optional[CADCoreLike]:
|
||||
# Sorting is required to improve hashcode consistency
|
||||
shapes_raw_filtered_sorted = sorted(shapes_raw_filtered, key=lambda x: _hashcode(x))
|
||||
# Build a single compound shape
|
||||
shapes_bd = [Shape(shape) for shape in shapes_raw_filtered_sorted if shape is not None]
|
||||
shapes_bd = [Compound(shape) for shape in shapes_raw_filtered_sorted if shape is not None]
|
||||
return get_shape(Compound(shapes_bd), error)
|
||||
except TypeError:
|
||||
pass
|
||||
@@ -121,11 +121,11 @@ def image_to_gltf(source: str | bytes, center: any, width: Optional[float] = Non
|
||||
hasher = hashlib.md5()
|
||||
hasher.update(source)
|
||||
name = 'image_' + hasher.hexdigest()
|
||||
format: str
|
||||
_format: str
|
||||
if save_mime == 'image/jpeg':
|
||||
format = 'JPEG'
|
||||
_format = 'JPEG'
|
||||
elif save_mime == 'image/png':
|
||||
format = 'PNG'
|
||||
_format = 'PNG'
|
||||
else:
|
||||
raise ValueError(f'Unsupported save MIME type (for GLTF files): {save_mime}')
|
||||
|
||||
@@ -154,7 +154,7 @@ def image_to_gltf(source: str | bytes, center: any, width: Optional[float] = Non
|
||||
img = img.resize((new_width, new_height))
|
||||
|
||||
# Save the image to a buffer
|
||||
img.save(img_buf, format=format)
|
||||
img.save(img_buf, format=_format)
|
||||
img_buf = img_buf.getvalue()
|
||||
|
||||
# Convert coordinates system as a last step (gltf is Y-up instead of Z-up)
|
||||
|
||||
@@ -169,6 +169,7 @@ class GLTFMgr:
|
||||
self.gltf.images = [Image(bufferView=len(buffers_list), mimeType=self.image[1])]
|
||||
self.gltf.textures = [Texture(source=0, sampler=0)]
|
||||
self.gltf.samplers = [Sampler(magFilter=NEAREST)]
|
||||
# noinspection PyPep8Naming
|
||||
self.gltf.materials[0].pbrMetallicRoughness.baseColorTexture = TextureInfo(index=0)
|
||||
buffers_list.append((Accessor(), BufferView(), self.image[0]))
|
||||
|
||||
|
||||
@@ -138,3 +138,4 @@ class HTTPHandler(SimpleHTTPRequestHandler):
|
||||
self.send_header('E-Tag', f'"{_hash}"')
|
||||
self.end_headers()
|
||||
self.wfile.write(exported_glb)
|
||||
return None
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import queue
|
||||
import queue
|
||||
import threading
|
||||
from typing import List, TypeVar, \
|
||||
Generic, Generator
|
||||
from typing import List, TypeVar, Generic, Generator
|
||||
|
||||
from yacv_server.mylogger import logger
|
||||
|
||||
@@ -58,7 +56,7 @@ class BufferedPubSub(Generic[T]):
|
||||
|
||||
def subscribe(self, include_buffered: bool = True, include_future: bool = True, yield_timeout: float = 0.0) -> \
|
||||
Generator[T, None, None]:
|
||||
"""Subscribes to events as an generator that yields events and automatically unsubscribes"""
|
||||
"""Subscribes to events as a generator that yields events and automatically unsubscribes"""
|
||||
q = self._subscribe(include_buffered, include_future)
|
||||
try:
|
||||
while True:
|
||||
|
||||
@@ -5,7 +5,7 @@ from OCP.BRepAdaptor import BRepAdaptor_Curve
|
||||
from OCP.GCPnts import GCPnts_TangentialDeflection
|
||||
from OCP.TopLoc import TopLoc_Location
|
||||
from OCP.TopoDS import TopoDS_Face, TopoDS_Edge, TopoDS_Shape, TopoDS_Vertex
|
||||
from build123d import Shape, Vertex, Face, Location
|
||||
from build123d import Vertex, Face, Location, Compound
|
||||
from pygltflib import GLTF2
|
||||
|
||||
from yacv_server.cad import CADCoreLike, ColorTuple
|
||||
@@ -33,7 +33,7 @@ def tessellate(
|
||||
mgr.add_location(Location(cad_like))
|
||||
|
||||
elif isinstance(cad_like, TopoDS_Shape):
|
||||
shape = Shape(cad_like)
|
||||
shape = Compound(cad_like)
|
||||
|
||||
# Perform tessellation tasks
|
||||
edge_to_faces: Dict[str, List[TopoDS_Face]] = {}
|
||||
@@ -59,6 +59,9 @@ def tessellate(
|
||||
for vertex in shape.vertices():
|
||||
_tessellate_vertex(mgr, vertex.wrapped, vertex_to_faces.get(vertex.wrapped, []), obj_color)
|
||||
|
||||
else:
|
||||
raise TypeError(f"Unsupported type: {type(cad_like)}: {cad_like}")
|
||||
|
||||
return mgr.build()
|
||||
|
||||
|
||||
@@ -69,9 +72,10 @@ def _tessellate_face(
|
||||
angular_tolerance: float = 0.1,
|
||||
color: Optional[ColorTuple] = None,
|
||||
):
|
||||
face = Shape(ocp_face)
|
||||
face = Compound(ocp_face)
|
||||
# face.mesh(tolerance, angular_tolerance)
|
||||
tri_mesh = face.tessellate(tolerance, angular_tolerance)
|
||||
# noinspection PyArgumentList
|
||||
poly = BRep_Tool.Triangulation_s(face.wrapped, TopLoc_Location())
|
||||
if poly is None:
|
||||
logger.warn("No triangulation found for face")
|
||||
@@ -86,6 +90,7 @@ def _tessellate_face(
|
||||
vertices = tri_mesh[0]
|
||||
indices = tri_mesh[1]
|
||||
mgr.add_face(vertices, indices, uv, color)
|
||||
return None
|
||||
|
||||
|
||||
def _push_point(v: Tuple[float, float, float], faces: List[TopoDS_Face]) -> Tuple[float, float, float]:
|
||||
|
||||
@@ -9,18 +9,18 @@ import threading
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from http.server import ThreadingHTTPServer
|
||||
from io import BytesIO
|
||||
from threading import Thread
|
||||
from typing import Optional, Dict, Union, Callable, List, Tuple
|
||||
|
||||
from OCP.TopLoc import TopLoc_Location
|
||||
from OCP.TopoDS import TopoDS_Shape
|
||||
# noinspection PyProtectedMember
|
||||
from build123d import Shape, Axis, Location, Vector, Color
|
||||
from dataclasses_json import dataclass_json
|
||||
from PIL import Image
|
||||
from io import BytesIO
|
||||
# noinspection PyProtectedMember
|
||||
from build123d import Shape, Axis, Location, Vector
|
||||
from dataclasses_json import dataclass_json
|
||||
|
||||
from yacv_server.cad import _hashcode, ColorTuple, get_color
|
||||
from yacv_server.cad import _hashcode, get_color
|
||||
from yacv_server.cad import get_shape, grab_all_cad, CADCoreLike, CADLike
|
||||
from yacv_server.gltf import get_version
|
||||
from yacv_server.myhttp import HTTPHandler
|
||||
@@ -95,7 +95,7 @@ class YACV:
|
||||
"""Default texture to use for model faces, in (data, mimetype) format.
|
||||
If left as None, a default checkerboard texture will be used.
|
||||
|
||||
It can be set with the YACV_BASE_TEXTURE=<uri> and overriden by `show(..., texture="<uri>")`.
|
||||
It can be set with the YACV_BASE_TEXTURE=<uri> and overridden by `show(..., texture="<uri>")`.
|
||||
The <uri> can be file:<path> or data:<mime>;base64,<data> where <mime> is the mime type and
|
||||
<data> is the base64 encoded image."""
|
||||
|
||||
@@ -331,6 +331,7 @@ class YACV:
|
||||
try:
|
||||
return next(subscription), event.hash
|
||||
finally:
|
||||
# noinspection PyInconsistentReturns
|
||||
subscription.close()
|
||||
|
||||
def export_all(self, folder: str,
|
||||
@@ -381,19 +382,30 @@ def _preprocess_cad(obj: CADLike, **kwargs) -> CADCoreLike:
|
||||
return obj
|
||||
|
||||
|
||||
_find_var_name_count = 0
|
||||
|
||||
_obj_name_counts = {}
|
||||
|
||||
def _find_var_name(obj: any, avoid_levels: int = 2) -> str:
|
||||
"""A hacky way to get a stable name for an object that may change over time"""
|
||||
global _find_var_name_count
|
||||
|
||||
# Build123d objects have a "label" property, CadQuery Assembly's have "name"
|
||||
for f in ('label', 'name'):
|
||||
if hasattr(obj, f):
|
||||
v = getattr(obj, f)
|
||||
if v != '':
|
||||
return v;
|
||||
|
||||
# Otherwise walk up our stack to see if there's a local variable that points to it
|
||||
obj_shape = get_shape(obj, error=False) or obj
|
||||
for frame in inspect.stack()[avoid_levels:]:
|
||||
for key, value in frame.frame.f_locals.items():
|
||||
if get_shape(value, error=False) is obj_shape:
|
||||
return key
|
||||
_find_var_name_count += 1
|
||||
return 'unknown_var_' + str(_find_var_name_count)
|
||||
|
||||
# Last resort, name it for its type with a disambiguating number
|
||||
global _obj_name_counts
|
||||
t = obj.__class__.__name__
|
||||
_obj_name_counts[t] = 1 if t not in _obj_name_counts else _obj_name_counts[t] + 1
|
||||
return t + str(_obj_name_counts[t])
|
||||
|
||||
|
||||
def sizeof_fmt(num, suffix="B"):
|
||||
|
||||
Reference in New Issue
Block a user