Skip to content

Release/2.0.0 #151

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

Draft
wants to merge 24 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e80b266
feat-wip: tentative planning added for DF2 development - TBD
DamienGilliard May 15, 2025
136e3dc
ADD Http Listener
eleniv3d May 15, 2025
38aab63
ADD TCP Listener
eleniv3d May 16, 2025
2fd80df
FIX lintering
eleniv3d May 27, 2025
aeecaa2
FIX tcp component + add example file sender
eleniv3d May 27, 2025
5cacef1
Merge branch 'main' into IO
eleniv3d May 28, 2025
4aafbf8
WIP FIX WS Receiver
eleniv3d May 28, 2025
e09fb79
FIX websocket component
eleniv3d Jun 17, 2025
46c6d6f
FIX light refactoring and input reorder
eleniv3d Jun 22, 2025
c546fec
ADD drop btns and panel with standard inputs similar to vizualization…
eleniv3d Jun 22, 2025
9964b85
feat-wip: add sequence schema of the df2 workflow as it is now developed
DamienGilliard Jul 22, 2025
8509138
FIX rename python file
eleniv3d Jul 24, 2025
2588656
FIX remove repeated ws from stickys
eleniv3d Jul 25, 2025
683b4e8
ADD warning if trying to load data from tcp/ws listener without start…
eleniv3d Jul 25, 2025
27cad32
ADD sleep to prevent CPU spin
eleniv3d Jul 25, 2025
bd004f7
ADD doc strings
eleniv3d Jul 25, 2025
b383bc1
FIX add docstrings
eleniv3d Jul 25, 2025
7f11249
FIX missing lines from PKG-INFO
eleniv3d Jul 25, 2025
484810f
FIX RML.Warning
eleniv3d Jul 25, 2025
4d287f2
FIX cleanup warnings that didnt work
eleniv3d Jul 30, 2025
c65b4ae
Merge pull request #152 from diffCheckOrg/IO
DamienGilliard Jul 30, 2025
f7b1ae6
Update code.py
DamienGilliard Jul 30, 2025
3d33b61
remove unused import
DamienGilliard Jul 30, 2025
f684ca0
Merge pull request #160 from diffCheckOrg/DamienGilliard-patch-3-to-m…
DamienGilliard Jul 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ repos:
types-requests==2.31.0,
numpy==2.0.1,
pytest==8.3.1,
websockets>=10.4,
types-setuptools>=71.1.0.20240818
]
args: [--config=pyproject.toml]
Expand Down
63 changes: 49 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,24 +64,59 @@ gantt
title diffCheck - general overview
excludes weekends

section Publication
Abstract edition :active, absed, 2024-03-01, 2024-03-15
Submission abstract ICSA :milestone, icsaabs, 2024-03-15, 0d
Paper edition :paperd, 2024-10-01, 2024-10-30
Submission paper ICSA :milestone, icsapap, 2024-10-30, 0d

section Code development
Backend development :backenddev, after icsaabs, 6w
Rhino/Grasshopper integration :rhghinteg, after backenddev, 6w
Documentation & Interface :docuint, after fabar, 3w
section Workshop
Workshop dryrun :milestone, crit, dryrun, 2025-09-15, 1d
Workshop in Boston :workshop, 2025-11-16, 2d

section Component development
Pose estimation :CD1, 2025-05-15, 1w
Communication w/ hardware :CD2, after CD1, 3w
Pose comparison :CD3, after CD1, 3w
General PC manipulation :CD4, after CD1, 6w
Data analysis component :CD5, after CD3, 3w

section Workshop preparation
Workshop scenario :doc1, 2025-08-01, 1w
New compilation documentation :doc2, after mac, 2w
New components documentation :doc2, 2025-08-01, 4w
Development of special pipeline for data:doc3, after doc1, 3w

section Cross-platform
adaptation of CMake for mac compilation :mac, 2025-07-01, 3w

section Prototype testing
Fabrication of AR Prototype :crit, fabar, 2024-07-01, 2024-08-30
Fabrication of CNC Prototype :crit, fabcnc, 2024-07-01, 2024-08-30
Fabrication of Robot Prototype :crit, fabrob, 2024-07-01, 2024-08-30
Data collection and evaluation :dataeval, after fabrob, 4w
Fabrication of iterative prototype :fab, 2025-08-01, 2w
```



## How to contribute

If you want to contribute to the project, please refer to the [contribution guidelines]([./CONTRIBUTING.md](https://diffcheckorg.github.io/diffCheck/contribute.html)).

## Logic
The logic of the workflow is currently as follows:

```mermaid
stateDiagram-v2
state "[breps to assemble]" as s1
state "scan of latest element placed" as s2
state "get pose of i-th brep" as s3
state "get pose of i-1-th brep" as s4
state "compute pose of i-1-th element from scan" as s5
state "compute pose difference" as s6
state "compute pose correction" as s7
state "assemble i-th-element" as s8
state "i += 1" as s9
[*]-->s2
s1-->s3
s1-->s4
s2-->s5
s5-->s6
s4-->s6
s6-->s7
s3-->s7
s7-->s8
s8-->s9
s9-->[*]
```
2 changes: 1 addition & 1 deletion deps/eigen
Submodule eigen updated from 11fd34 to 81044e
2 changes: 1 addition & 1 deletion deps/pybind11
Submodule pybind11 updated 144 files
Binary file modified environment.yml
Binary file not shown.
136 changes: 136 additions & 0 deletions src/gh/components/DF_http_listener/code.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#! python3

from ghpythonlib.componentbase import executingcomponent as component
import os
import tempfile
import requests
import threading
import Rhino
import Rhino.Geometry as rg
import scriptcontext as sc
from diffCheck import df_gh_canvas_utils


class DFHTTPListener(component):

def __init__(self):
try:
ghenv.Component.ExpireSolution(True) # noqa: F821
ghenv.Component.Attributes.PerformLayout() # noqa: F821
except NameError:
pass

df_gh_canvas_utils.add_button(ghenv.Component, "Load", 0, x_offset=60) # noqa: F821
df_gh_canvas_utils.add_panel(ghenv.Component, "Ply_url", "https://github.com/diffCheckOrg/diffCheck/raw/refs/heads/main/tests/test_data/cube_mesh.ply", 1, 60, 20) # noqa: F821

def RunScript(self,
i_load: bool,
i_ply_url: str):

prefix = 'http'

# initialize sticky variables
sc.sticky.setdefault(f'{prefix}_ply_url', None) # last url processed
sc.sticky.setdefault(f'{prefix}_imported_geom', None) # last geo imported from ply
sc.sticky.setdefault(f'{prefix}_status_message', "Waiting..") # status message on component
sc.sticky.setdefault(f'{prefix}_prev_load', False) # previous state of toggle
sc.sticky.setdefault(f'{prefix}_thread_running', False) # is a background thread running?

def _import_job(url: str) -> None:

"""
Downloads and imports a .ply file from a given URL in a background thread.
Background job:
- Downloads the .ply file from the URL
- Imports it into the active Rhino document
- Extracts the new geometry (point cloud or mesh)
- Cleans up the temporary file and document objects
- Updates sticky state and status message
- Signals to GH that it should re-solve

:param url: A string representing a direct URL to a .ply file (e.g. from GitHub or local server).
The file must end with ".ply".
:returns: None
"""

tmp = None
try:
if not url.lower().endswith('.ply'):
raise ValueError("URL must end in .ply")

resp = requests.get(url, timeout=30)
resp.raise_for_status()
# save om temporary file
fn = os.path.basename(url)
tmp = os.path.join(tempfile.gettempdir(), fn)
with open(tmp, 'wb') as f:
f.write(resp.content)

doc = Rhino.RhinoDoc.ActiveDoc
# recordd existing object IDs to detect new ones
before_ids = {o.Id for o in doc.Objects}

# import PLY using Rhino's API
opts = Rhino.FileIO.FilePlyReadOptions()
ok = Rhino.FileIO.FilePly.Read(tmp, doc, opts)
if not ok:
raise RuntimeError("Rhino.FilePly.Read failed")

after_ids = {o.Id for o in doc.Objects}
new_ids = after_ids - before_ids
# get new pcd or mesh from document
geom = None
for guid in new_ids:
g = doc.Objects.FindId(guid).Geometry
if isinstance(g, rg.PointCloud):
geom = g.Duplicate()
break
elif isinstance(g, rg.Mesh):
geom = g.DuplicateMesh()
break
# remove imported objects
for guid in new_ids:
doc.Objects.Delete(guid, True)
doc.Views.Redraw()

# store new geometry
sc.sticky[f'{prefix}_imported_geom'] = geom
count = geom.Count if isinstance(geom, rg.PointCloud) else geom.Vertices.Count
if isinstance(geom, rg.PointCloud):
sc.sticky[f'{prefix}_status_message'] = f"Loaded pcd with {count} pts"
else:
sc.sticky[f'{prefix}_status_message'] = f"Loaded mesh wih {count} vertices"
ghenv.Component.Message = sc.sticky.get(f'{prefix}_status_message') # noqa: F821

except Exception as e:
sc.sticky[f'{prefix}_imported_geom'] = None
sc.sticky[f'{prefix}_status_message'] = f"Error: {e}"
finally:
try:
os.remove(tmp)
except Exception:
pass
# mark thread as finished
sc.sticky[f'{prefix}_thread_running'] = False
ghenv.Component.ExpireSolution(True) # noqa: F821

# check if the URL input has changed
if sc.sticky[f'{prefix}_ply_url'] != i_ply_url:
sc.sticky[f'{prefix}_ply_url'] = i_ply_url
sc.sticky[f'{prefix}_status_message'] = "URL changed. Press Load"
sc.sticky[f'{prefix}_thread_running'] = False
sc.sticky[f'{prefix}_prev_load'] = False

# start importing if Load toggle is pressed and import thread is not already running
if i_load and not sc.sticky[f'{prefix}_prev_load'] and not sc.sticky[f'{prefix}_thread_running']:
sc.sticky[f'{prefix}_status_message'] = "Loading..."
sc.sticky[f'{prefix}_thread_running'] = True
threading.Thread(target=_import_job, args=(i_ply_url,), daemon=True).start()

sc.sticky[f'{prefix}_prev_load'] = i_load
ghenv.Component.Message = sc.sticky.get(f'{prefix}_status_message', "") # noqa: F821

# output
o_geometry = sc.sticky.get(f'{prefix}_imported_geom')

return [o_geometry]
Binary file added src/gh/components/DF_http_listener/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 52 additions & 0 deletions src/gh/components/DF_http_listener/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"name": "DFHTTPListener",
"nickname": "HTTPIn",
"category": "diffCheck",
"subcategory": "IO",
"description": "This component reads a ply file from the internet.",
"exposure": 4,
"instanceGuid": "ca4b5c94-6c85-4bc5-87f0-132cc34c4536",
"ghpython": {
"hideOutput": true,
"hideInput": true,
"isAdvancedMode": true,
"marshalOutGuids": true,
"iconDisplay": 2,
"inputParameters": [
{
"name": "i_load",
"nickname": "i_load",
"description": "Button to import ply from url.",
"optional": true,
"allowTreeAccess": true,
"showTypeHints": true,
"scriptParamAccess": "item",
"wireDisplay": "default",
"sourceCount": 0,
"typeHintID": "bool"
},
{
"name": "i_ply_url",
"nickname": "i_ply_url",
"description": "The url where to get the pointcloud",
"optional": true,
"allowTreeAccess": true,
"showTypeHints": true,
"scriptParamAccess": "item",
"wireDisplay": "default",
"sourceCount": 0,
"typeHintID": "str"
}
],
"outputParameters": [
{
"name": "o_geometry",
"nickname": "o_geo",
"description": "The mesh or pcd that was imported.",
"optional": false,
"sourceCount": 0,
"graft": false
}
]
}
}
Loading
Loading