Skip to content

Commit c1741b2

Browse files
authored
Issue #17 (#18)
* Make code more clear. * Sketch::update_faces_() handle dangling edges * Dangling edges unit test. * AI improved sketch edge cases. * wip * Save persist view * Refactor * Update gitignore * Delete single platform CMake workflow Removed the CMake workflow for a single platform, which included steps for building, testing, and installing OpenCASCADE.
1 parent 9008d14 commit c1741b2

7 files changed

Lines changed: 633 additions & 172 deletions

File tree

Lines changed: 0 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1,152 +1 @@
1-
# This starter workflow is for a CMake project running on a single platform. There is a different starter workflow if you need cross-platform coverage.
2-
# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-multi-platform.yml
3-
name: CMake on a single platform
41

5-
on:
6-
push:
7-
branches: [ "main" ]
8-
pull_request:
9-
branches: [ "main" ]
10-
11-
env:
12-
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
13-
BUILD_TYPE: Release
14-
15-
jobs:
16-
build:
17-
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
18-
# You can convert this to a matrix build if you need cross-platform coverage.
19-
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
20-
runs-on: windows-latest
21-
22-
steps:
23-
- uses: actions/checkout@v4
24-
25-
- name: Install NuGet
26-
uses: nuget/setup-nuget@v1
27-
with:
28-
nuget-version: 'latest'
29-
30-
- name: Setup vcpkg
31-
uses: friendlyanon/setup-vcpkg@v1
32-
33-
- name: Try to download pre-built OpenCASCADE
34-
id: download_occt
35-
shell: pwsh
36-
continue-on-error: true
37-
run: |
38-
$OCCT_VERSION = "7.9.1"
39-
$OCCT_EXTRACT_DIR = "$env:RUNNER_TEMP\occt"
40-
$OCCT_ZIP = "$env:RUNNER_TEMP\occt.zip"
41-
42-
# Try multiple possible download URLs
43-
$urls = @(
44-
"https://github.com/Open-Cascade-SAS/OCCT/releases/download/V7_9_1/opencascade-$OCCT_VERSION-vc14-64.zip",
45-
"https://github.com/Open-Cascade-SAS/OCCT/releases/download/V7_9_1/OCC-$OCCT_VERSION-VC14-64.zip",
46-
"https://dev.opencascade.org/system/files/occt/opencascade-$OCCT_VERSION-vc14-64.zip",
47-
"https://dev.opencascade.org/system/files/occt/OCC-$OCCT_VERSION-VC14-64.zip"
48-
)
49-
50-
$downloaded = $false
51-
foreach ($url in $urls) {
52-
try {
53-
Write-Host "Trying to download from: $url"
54-
Invoke-WebRequest -Uri $url -OutFile $OCCT_ZIP -UseBasicParsing -TimeoutSec 30
55-
Write-Host "Successfully downloaded from: $url"
56-
$downloaded = $true
57-
break
58-
} catch {
59-
Write-Host "Failed to download from $url : $_"
60-
continue
61-
}
62-
}
63-
64-
if ($downloaded) {
65-
Write-Host "Extracting OpenCASCADE..."
66-
if (Test-Path $OCCT_EXTRACT_DIR) {
67-
Remove-Item -Path $OCCT_EXTRACT_DIR -Recurse -Force
68-
}
69-
Expand-Archive -Path $OCCT_ZIP -DestinationPath $OCCT_EXTRACT_DIR -Force
70-
71-
# Find OpenCASCADEConfig.cmake
72-
$OCCT_CONFIG = Get-ChildItem -Path $OCCT_EXTRACT_DIR -Recurse -Filter "OpenCASCADEConfig.cmake" -ErrorAction SilentlyContinue | Select-Object -First 1
73-
if ($OCCT_CONFIG) {
74-
$OCCT_CMAKE_DIR = $OCCT_CONFIG.DirectoryName
75-
Write-Host "Found OpenCASCADE CMake config at: $OCCT_CMAKE_DIR"
76-
echo "OpenCASCADE_DIR=$OCCT_CMAKE_DIR" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
77-
echo "USE_VCPKG=false" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
78-
echo "Pre-built binaries found" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
79-
} else {
80-
Write-Host "Warning: Downloaded but could not find OpenCASCADEConfig.cmake"
81-
echo "USE_VCPKG=true" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
82-
}
83-
} else {
84-
Write-Host "Could not download pre-built binaries, will use vcpkg"
85-
echo "USE_VCPKG=true" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
86-
}
87-
88-
- name: Install OpenCASCADE via vcpkg (if needed)
89-
if: env.USE_VCPKG == 'true'
90-
shell: pwsh
91-
run: |
92-
Write-Host "Installing OpenCASCADE via vcpkg (this may take several minutes)..."
93-
vcpkg install opencascade:x64-windows --triplet x64-windows
94-
95-
- name: Find OpenCASCADE CMake config (vcpkg)
96-
if: env.USE_VCPKG == 'true'
97-
shell: pwsh
98-
run: |
99-
$VCPKG_INSTALLED = "$env:VCPKG_ROOT\installed\x64-windows"
100-
101-
# Find OpenCASCADEConfig.cmake
102-
$OCCT_CONFIG = Get-ChildItem -Path $VCPKG_INSTALLED -Recurse -Filter "OpenCASCADEConfig.cmake" -ErrorAction SilentlyContinue | Select-Object -First 1
103-
if ($OCCT_CONFIG) {
104-
$OCCT_CMAKE_DIR = $OCCT_CONFIG.DirectoryName
105-
Write-Host "Found OpenCASCADE CMake config at: $OCCT_CMAKE_DIR"
106-
echo "OpenCASCADE_DIR=$OCCT_CMAKE_DIR" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
107-
} else {
108-
# Try common vcpkg locations
109-
$possiblePaths = @(
110-
"$VCPKG_INSTALLED\share\opencascade",
111-
"$VCPKG_INSTALLED\share\occt"
112-
)
113-
foreach ($path in $possiblePaths) {
114-
if (Test-Path $path) {
115-
Write-Host "Using OpenCASCADE path: $path"
116-
echo "OpenCASCADE_DIR=$path" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
117-
break
118-
}
119-
}
120-
}
121-
122-
Write-Host "OpenCASCADE_DIR is set to: $env:OpenCASCADE_DIR"
123-
124-
- name: Configure CMake
125-
shell: pwsh
126-
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
127-
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
128-
run: |
129-
$cmakeArgs = @(
130-
"-B", "${{github.workspace}}\build",
131-
"-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}",
132-
"-DOpenCASCADE_DIR=`"${{env.OpenCASCADE_DIR}}`""
133-
)
134-
135-
if ("${{env.USE_VCPKG}}" -eq "true") {
136-
$cmakeArgs += "-DCMAKE_TOOLCHAIN_FILE=`"$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake`""
137-
$cmakeArgs += "-DVCPKG_TARGET_TRIPLET=x64-windows"
138-
}
139-
140-
cmake @cmakeArgs
141-
142-
- name: Build
143-
shell: pwsh
144-
# Build your program with the given configuration
145-
run: cmake --build ${{github.workspace}}\build --config ${{env.BUILD_TYPE}}
146-
147-
- name: Test
148-
working-directory: ${{github.workspace}}\build
149-
shell: pwsh
150-
# Execute tests defined by the CMake configuration.
151-
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
152-
run: ctest -C ${{env.BUILD_TYPE}} --output-on-failure

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@
2121
/build2/.vs
2222
/build2
2323
/.vs
24+
/.vscode/settings.json

src/modes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ enum class Mode
99
Move,
1010
Scale,
1111
Rotate,
12-
Sketch_inspection_mode, // For inspecting sketch elements
12+
Sketch_inspection_mode, // For inspecting sketch elements
1313
Sketch_from_face, // For creating a sketch from a face
1414
Sketch_face_extrude, // For extruding a sketch face
1515
Shape_chamfer, // For chamfering a shape

src/occt_view.cpp

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "sketch.h"
2828
#include "sketch_json.h"
2929
#include "utl.h"
30+
#include "utl_json.h"
3031

3132
#ifdef __EMSCRIPTEN__
3233
#include <Wasm_Window.hxx>
@@ -1036,7 +1037,15 @@ std::string Occt_view::to_json() const
10361037
using namespace nlohmann;
10371038
json j;
10381039
json& sketches = j["sketches"] = json::array();
1039-
json& shps = j["shapes"] = json::array();
1040+
json& shps = j["shapes"] = json::array();
1041+
1042+
const auto pnt_to_json = [](Standard_Real x, Standard_Real y, Standard_Real z)
1043+
{
1044+
return ::to_json(gp_Pnt(x, y, z));
1045+
};
1046+
1047+
// ---------------------------------------------------------------------------
1048+
// Sketches / shapes
10401049
for (const Sketch_ptr& s : m_sketches)
10411050
sketches.push_back(Sketch_json::to_json(*s));
10421051

@@ -1053,6 +1062,34 @@ std::string Occt_view::to_json() const
10531062
shps.push_back(shp_json);
10541063
}
10551064

1065+
// ---------------------------------------------------------------------------
1066+
// View / camera state
1067+
if (!m_view.IsNull())
1068+
{
1069+
json& view_json = j["view"];
1070+
1071+
// Eye and target (At) positions
1072+
Standard_Real eye_x, eye_y, eye_z;
1073+
Standard_Real at_x, at_y, at_z;
1074+
m_view->Eye(eye_x, eye_y, eye_z);
1075+
m_view->At(at_x, at_y, at_z);
1076+
1077+
view_json["eye"] = pnt_to_json(eye_x, eye_y, eye_z);
1078+
view_json["at"] = pnt_to_json(at_x, at_y, at_z);
1079+
1080+
// Up and projection directions
1081+
Standard_Real up_x, up_y, up_z;
1082+
Standard_Real proj_x, proj_y, proj_z;
1083+
m_view->Up(up_x, up_y, up_z);
1084+
m_view->Proj(proj_x, proj_y, proj_z);
1085+
1086+
view_json["up"] = ::to_json(gp_Dir(up_x, up_y, up_z));
1087+
view_json["proj"] = ::to_json(gp_Dir(proj_x, proj_y, proj_z));
1088+
1089+
// View scale (zoom level)
1090+
view_json["scale"] = m_view->Scale();
1091+
}
1092+
10561093
return j.dump(2);
10571094
}
10581095

@@ -1106,6 +1143,53 @@ void Occt_view::load(const std::string& json_str)
11061143
m_ctx->Display(shp, AIS_Shaded, 0, true);
11071144
}
11081145

1146+
// ---------------------------------------------------------------------------
1147+
// Restore view / camera state if present
1148+
if (!m_view.IsNull() && j.contains("view") && j["view"].is_object())
1149+
{
1150+
const json& view_json = j["view"];
1151+
try
1152+
{
1153+
if (view_json.contains("eye") && view_json["eye"].is_object())
1154+
{
1155+
gp_Pnt eye = from_json_pnt(view_json["eye"]);
1156+
m_view->SetEye(eye.X(), eye.Y(), eye.Z());
1157+
}
1158+
1159+
if (view_json.contains("at") && view_json["at"].is_object())
1160+
{
1161+
gp_Pnt at = from_json_pnt(view_json["at"]);
1162+
m_view->SetAt(at.X(), at.Y(), at.Z());
1163+
}
1164+
1165+
if (view_json.contains("up") && view_json["up"].is_object())
1166+
{
1167+
gp_Dir up = from_json_dir(view_json["up"]);
1168+
m_view->SetUp(up.X(), up.Y(), up.Z());
1169+
}
1170+
1171+
if (view_json.contains("proj") && view_json["proj"].is_object())
1172+
{
1173+
gp_Dir dir = from_json_dir(view_json["proj"]);
1174+
m_view->SetProj(dir.X(), dir.Y(), dir.Z());
1175+
}
1176+
1177+
if (view_json.contains("scale") && view_json["scale"].is_number())
1178+
{
1179+
const Standard_Real scale = view_json["scale"].get<Standard_Real>();
1180+
if (scale > Precision::Confusion())
1181+
m_view->SetScale(scale);
1182+
}
1183+
1184+
m_view->Redraw();
1185+
m_ctx->UpdateCurrentViewer();
1186+
}
1187+
catch (const std::exception&)
1188+
{
1189+
// Ignore view restoration errors; project geometry has already loaded.
1190+
}
1191+
}
1192+
11091193
// Ensure correct state
11101194
gui().set_mode(Mode::Normal);
11111195
}

0 commit comments

Comments
 (0)