diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 3357bf74..ff096349 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -34,10 +34,10 @@ jobs:
mkdir -p AppDir/usr/bin
mkdir -p AppDir/usr/share/applications
mkdir -p AppDir/usr/share/icons/hicolor/256x256/apps
- cp target/release/H7CAD AppDir/usr/bin/H7CAD
- cp packaging/H7CAD.desktop AppDir/usr/share/applications/io.github.HakanSeven12.H7CAD.desktop
+ cp target/release/OpenCADStudio AppDir/usr/bin/OpenCADStudio
+ cp packaging/OpenCADStudio.desktop AppDir/usr/share/applications/io.github.HakanSeven12.OpenCadStudio.desktop
rsvg-convert -w 256 -h 256 assets/logo.svg \
- -o AppDir/usr/share/icons/hicolor/256x256/apps/io.github.HakanSeven12.H7CAD.png
+ -o AppDir/usr/share/icons/hicolor/256x256/apps/io.github.HakanSeven12.OpenCadStudio.png
- name: Download linuxdeploy
run: |
@@ -50,18 +50,18 @@ jobs:
run: |
./linuxdeploy-x86_64.AppImage \
--appdir AppDir \
- --desktop-file AppDir/usr/share/applications/io.github.HakanSeven12.H7CAD.desktop \
- --icon-file AppDir/usr/share/icons/hicolor/256x256/apps/io.github.HakanSeven12.H7CAD.png \
+ --desktop-file AppDir/usr/share/applications/io.github.HakanSeven12.OpenCadStudio.desktop \
+ --icon-file AppDir/usr/share/icons/hicolor/256x256/apps/io.github.HakanSeven12.OpenCadStudio.png \
--output appimage
- mv H7CAD*.AppImage H7CAD.AppImage
+ mv Open*CAD*Studio*.AppImage OpenCADStudio.AppImage
- name: Upload AppImage to release
if: github.event_name == 'release'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
- mv H7CAD.AppImage H7CAD-${{ github.ref_name }}-linux-x86_64.AppImage
- gh release upload ${{ github.ref_name }} H7CAD-${{ github.ref_name }}-linux-x86_64.AppImage --clobber --repo ${{ github.repository }}
+ mv OpenCADStudio.AppImage OpenCADStudio-${{ github.ref_name }}-linux-x86_64.AppImage
+ gh release upload ${{ github.ref_name }} OpenCADStudio-${{ github.ref_name }}-linux-x86_64.AppImage --clobber --repo ${{ github.repository }}
build-windows:
runs-on: windows-latest
@@ -83,8 +83,8 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
- mv target/release/H7CAD.exe H7CAD-${{ github.ref_name }}-windows-x86_64.exe
- gh release upload ${{ github.ref_name }} H7CAD-${{ github.ref_name }}-windows-x86_64.exe --clobber --repo ${{ github.repository }}
+ mv target/release/OpenCADStudio.exe OpenCADStudio-${{ github.ref_name }}-windows-x86_64.exe
+ gh release upload ${{ github.ref_name }} OpenCADStudio-${{ github.ref_name }}-windows-x86_64.exe --clobber --repo ${{ github.repository }}
build-macos:
runs-on: macos-14 # Apple Silicon (arm64) only
@@ -110,25 +110,25 @@ jobs:
- name: Build .icns from SVG
run: |
- mkdir -p H7CAD.iconset
+ mkdir -p OpenCADStudio.iconset
# Render all the sizes Apple expects in an .icns.
for SIZE in 16 32 64 128 256 512 1024; do
- rsvg-convert -w $SIZE -h $SIZE assets/logo.svg -o H7CAD.iconset/icon_${SIZE}x${SIZE}.png
+ rsvg-convert -w $SIZE -h $SIZE assets/logo.svg -o OpenCADStudio.iconset/icon_${SIZE}x${SIZE}.png
done
# @2x retina variants (half-size base name)
for BASE in 16 32 128 256 512; do
DOUBLE=$((BASE * 2))
- cp H7CAD.iconset/icon_${DOUBLE}x${DOUBLE}.png H7CAD.iconset/icon_${BASE}x${BASE}@2x.png
+ cp OpenCADStudio.iconset/icon_${DOUBLE}x${DOUBLE}.png OpenCADStudio.iconset/icon_${BASE}x${BASE}@2x.png
done
- iconutil -c icns H7CAD.iconset -o AppIcon.icns
+ iconutil -c icns OpenCADStudio.iconset -o AppIcon.icns
- name: Assemble .app bundle
run: |
- APP=H7CAD.app
+ APP=OpenCADStudio.app
rm -rf "$APP"
mkdir -p "$APP/Contents/MacOS" "$APP/Contents/Resources"
- cp target/aarch64-apple-darwin/release/H7CAD "$APP/Contents/MacOS/H7CAD"
- chmod +x "$APP/Contents/MacOS/H7CAD"
+ cp target/aarch64-apple-darwin/release/OpenCADStudio "$APP/Contents/MacOS/OpenCADStudio"
+ chmod +x "$APP/Contents/MacOS/OpenCADStudio"
cp AppIcon.icns "$APP/Contents/Resources/AppIcon.icns"
# Substitute version into Info.plist.
VERSION="${{ github.ref_name }}"
@@ -139,15 +139,15 @@ jobs:
- name: Create .dmg
run: |
hdiutil create \
- -volname "H7CAD" \
- -srcfolder H7CAD.app \
+ -volname "Open CAD Studio" \
+ -srcfolder OpenCADStudio.app \
-ov -format UDZO \
- H7CAD.dmg
+ OpenCADStudio.dmg
- name: Upload .dmg to release
if: github.event_name == 'release'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
- mv H7CAD.dmg H7CAD-${{ github.ref_name }}-macos-arm64.dmg
- gh release upload ${{ github.ref_name }} H7CAD-${{ github.ref_name }}-macos-arm64.dmg --clobber --repo ${{ github.repository }}
+ mv OpenCADStudio.dmg OpenCADStudio-${{ github.ref_name }}-macos-arm64.dmg
+ gh release upload ${{ github.ref_name }} OpenCADStudio-${{ github.ref_name }}-macos-arm64.dmg --clobber --repo ${{ github.repository }}
diff --git a/.gitignore b/.gitignore
index b12df8ac..7acd88e1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,7 +15,7 @@ target
# Flatpak
flatpak/cargo-sources.json
-flatpak/io.github.HakanSeven12.H7CAD.local.yml
+flatpak/io.github.HakanSeven12.OpenCadStudio.local.yml
.flatpak-builder/
build-dir/
diff --git a/COMMANDS.md b/COMMANDS.md
index 91d1374e..ff54c13c 100644
--- a/COMMANDS.md
+++ b/COMMANDS.md
@@ -1,6 +1,6 @@
-# H7CAD β Command Reference
+# Open CAD Studio β Command Reference
-Status of every standard CAD command in H7CAD:
+Status of every standard CAD command in Open CAD Studio:
- β
**Implemented** β fully working
- πΆ **Partial** β command is accepted but logic is a stub
diff --git a/Cargo.lock b/Cargo.lock
index 1e6e14ac..55f97c5d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,7 +3,7 @@
version = 4
[[package]]
-name = "H7CAD"
+name = "OpenCADStudio"
version = "0.3.8"
dependencies = [
"acadrust",
diff --git a/Cargo.toml b/Cargo.toml
index c60acc76..22b73d62 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,5 @@
[package]
-name = "H7CAD"
+name = "OpenCADStudio"
version = "0.3.8"
edition = "2021"
build = "build.rs"
diff --git a/README.md b/README.md
index 371615e4..fcebc88a 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# H7CAD
+# Open CAD Studio
@@ -102,34 +102,34 @@ A CAD application for 2D drafting and 3D modeling, built with Rust. Reads and wr
### Linux (AppImage)
-Download `H7CAD-*-linux-x86_64.AppImage` from the [latest release](https://github.com/HakanSeven12/H7CAD/releases/latest), then:
+Download `OpenCADStudio-*-linux-x86_64.AppImage` from the [latest release](https://github.com/HakanSeven12/open-cad-studio/releases/latest), then:
```bash
-chmod +x H7CAD-*-linux-x86_64.AppImage
-./H7CAD-*-linux-x86_64.AppImage
+chmod +x OpenCADStudio-*-linux-x86_64.AppImage
+./OpenCADStudio-*-linux-x86_64.AppImage
```
No installation required β runs directly on any modern Linux distribution.
### Windows
-Download `H7CAD-*-windows-x86_64.exe` from the [latest release](https://github.com/HakanSeven12/H7CAD/releases/latest) and run it directly. Windows SmartScreen may show "Windows protected your PC" because the binary is not yet code-signed β click **More info β Run anyway**.
+Download `OpenCADStudio-*-windows-x86_64.exe` from the [latest release](https://github.com/HakanSeven12/open-cad-studio/releases/latest) and run it directly. Windows SmartScreen may show "Windows protected your PC" because the binary is not yet code-signed β click **More info β Run anyway**.
### macOS (Apple Silicon)
-Download `H7CAD-*-macos-arm64.dmg` from the [latest release](https://github.com/HakanSeven12/H7CAD/releases/latest) β Apple Silicon (M-series) only; Intel macOS isn't built.
+Download `OpenCADStudio-*-macos-arm64.dmg` from the [latest release](https://github.com/HakanSeven12/open-cad-studio/releases/latest) β Apple Silicon (M-series) only; Intel macOS isn't built.
-Open the .dmg and drag `H7CAD.app` to `/Applications`. The first launch may be blocked by Gatekeeper because the app is not notarised β right-click `H7CAD.app β Open` and confirm, or run once via `xattr -dr com.apple.quarantine /Applications/H7CAD.app`.
+Open the .dmg and drag `OpenCADStudio.app` to `/Applications`. The first launch may be blocked by Gatekeeper because the app is not notarised β right-click `OpenCADStudio.app β Open` and confirm, or run once via `xattr -dr com.apple.quarantine /Applications/OpenCADStudio.app`.
### Build from Source
Requirements: Rust 1.75+
```bash
-git clone https://github.com/HakanSeven12/H7CAD.git
-cd H7CAD
-cargo build --release --bin H7CAD
-./target/release/H7CAD
+git clone https://github.com/HakanSeven12/open-cad-studio.git
+cd open-cad-studio
+cargo build --release --bin OpenCADStudio
+./target/release/OpenCADStudio
```
## License
diff --git a/ROADMAP.md b/ROADMAP.md
index bbf64d7d..33a79ad2 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -1,4 +1,4 @@
-# H7CAD β File Open & Render Speed Roadmap
+# Open CAD Studio β File Open & Render Speed Roadmap
This document lists the planned improvements for cutting **file open time**
and **on-screen draw (render) time**. It builds on the already-landed
@@ -91,7 +91,7 @@ decode until **first render** (per-handle lazy `OnceCell`).
### 1.7 File-hash cache (warm re-open)
When re-opening the same file (`(path, mtime, size)` key) keep a disk
-snapshot of `CadDocument` + `DerivedCaches` (e.g. `~/.cache/h7cad/`). Skip
+snapshot of `CadDocument` + `DerivedCaches` (e.g. `~/.cache/open-cad-studio/`). Skip
DWG parse entirely. **Win:** most-recently-opened file goes from 1-2 s to
sub-100 ms.
@@ -278,6 +278,6 @@ Then, measurement-guided:
- **GPU compute culling:** for orthographic 2D CAD the CPU quadtree is
enough. Already covered by Phase 1-4.
- **Out-of-core entity streaming:** meaningful for 100 MB+ single files;
- typical H7CAD files are not there yet.
+ typical Open CAD Studio files are not there yet.
- **Multi-frame async tessellation pipeline:** if 2.3 progressive render
works cleanly, this isn't needed.
diff --git a/assets/linetypes/H7CAD.lin b/assets/linetypes/OpenCADStudio.lin
similarity index 100%
rename from assets/linetypes/H7CAD.lin
rename to assets/linetypes/OpenCADStudio.lin
diff --git a/assets/logo.svg b/assets/logo.svg
index 490060df..aa1d0409 100644
--- a/assets/logo.svg
+++ b/assets/logo.svg
@@ -29,60 +29,26 @@
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg8" />
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/patterns/H7CAD.pat b/assets/patterns/OpenCADStudio.pat
similarity index 100%
rename from assets/patterns/H7CAD.pat
rename to assets/patterns/OpenCADStudio.pat
diff --git a/examples/dump_index_stats.rs b/examples/dump_index_stats.rs
deleted file mode 100644
index 482edfa6..00000000
--- a/examples/dump_index_stats.rs
+++ /dev/null
@@ -1,171 +0,0 @@
-// Diagnostic: simulate Scene::entity_index() build on a DXF/DWG file
-// and report per-type stats for indexed / unbounded / unindexable
-// entities, plus how many would survive a hypothetical view query.
-//
-// cargo run --release --example dump_index_stats --
-
-use acadrust::EntityType;
-use std::collections::BTreeMap;
-
-fn entity_kind(e: &EntityType) -> &'static str {
- match e {
- EntityType::Line(_) => "Line",
- EntityType::LwPolyline(_) => "LwPolyline",
- EntityType::Polyline2D(_) => "Polyline2D",
- EntityType::Polyline3D(_) => "Polyline3D",
- EntityType::Polyline(_) => "Polyline",
- EntityType::Circle(_) => "Circle",
- EntityType::Arc(_) => "Arc",
- EntityType::Ellipse(_) => "Ellipse",
- EntityType::Spline(_) => "Spline",
- EntityType::Text(_) => "Text",
- EntityType::MText(_) => "MText",
- EntityType::Hatch(_) => "Hatch",
- EntityType::Wipeout(_) => "Wipeout",
- EntityType::Insert(_) => "Insert",
- EntityType::Viewport(_) => "Viewport",
- EntityType::Block(_) => "Block",
- EntityType::BlockEnd(_) => "BlockEnd",
- EntityType::Dimension(_) => "Dimension",
- EntityType::Leader(_) => "Leader",
- EntityType::MLine(_) => "MLine",
- EntityType::Point(_) => "Point",
- EntityType::Solid(_) => "Solid",
- EntityType::Face3D(_) => "Face3D",
- EntityType::RasterImage(_) => "RasterImage",
- EntityType::Solid3D(_) => "Solid3D",
- EntityType::Region(_) => "Region",
- EntityType::Body(_) => "Body",
- EntityType::Ole2Frame(_) => "Ole2Frame",
- EntityType::Ray(_) => "Ray",
- EntityType::XLine(_) => "XLine",
- _ => "Other",
- }
-}
-
-fn is_unindexable(e: &EntityType) -> bool {
- matches!(
- e,
- EntityType::Insert(_)
- | EntityType::Viewport(_)
- | EntityType::Block(_)
- | EntityType::BlockEnd(_)
- )
-}
-
-fn world_aabb_f64(e: &EntityType) -> Option<[f64; 4]> {
- let bb = e.as_entity().bounding_box();
- let (xmin, ymin, xmax, ymax) = (bb.min.x, bb.min.y, bb.max.x, bb.max.y);
- if xmin == xmax && ymin == ymax {
- return None;
- }
- if !xmin.is_finite() || !ymin.is_finite() || !xmax.is_finite() || !ymax.is_finite() {
- return None;
- }
- Some([xmin, ymin, xmax, ymax])
-}
-
-fn main() -> Result<(), Box> {
- let path = std::env::args().nth(1).expect("usage: dump_index_stats ");
- let mut doc = if path.to_lowercase().ends_with(".dwg") {
- acadrust::io::dwg::DwgReader::from_file(&path)?.read()?
- } else {
- acadrust::io::dxf::DxfReader::from_file(&path)?.read()?
- };
- let base_dir = std::path::Path::new(&path)
- .parent()
- .unwrap_or(std::path::Path::new("."));
- let _ = H7CAD::io::xref::resolve_xrefs(&mut doc, base_dir);
-
- let model_block = doc.header.model_space_block_handle;
- println!("file: {}", path);
- println!("model_space_block_handle: {:?}", model_block);
- println!("total entities: {}", doc.entities().count());
- println!();
-
- let mut total: BTreeMap<&str, usize> = BTreeMap::new();
- let mut indexed: BTreeMap<&str, usize> = BTreeMap::new();
- let mut unbounded: BTreeMap<&str, usize> = BTreeMap::new();
- let mut unindexable_count: BTreeMap<&str, usize> = BTreeMap::new();
- let mut top_level: BTreeMap<&str, usize> = BTreeMap::new();
- let mut block_internal: BTreeMap<&str, usize> = BTreeMap::new();
- let mut union: Option<[f64; 4]> = None;
-
- for e in doc.entities() {
- let k = entity_kind(e);
- *total.entry(k).or_default() += 1;
- let owner = e.common().owner_handle;
- if owner == model_block {
- *top_level.entry(k).or_default() += 1;
- } else {
- *block_internal.entry(k).or_default() += 1;
- }
- if is_unindexable(e) {
- *unindexable_count.entry(k).or_default() += 1;
- continue;
- }
- match world_aabb_f64(e) {
- Some(ab) => {
- *indexed.entry(k).or_default() += 1;
- union = Some(match union {
- None => ab,
- Some(u) => [
- u[0].min(ab[0]),
- u[1].min(ab[1]),
- u[2].max(ab[2]),
- u[3].max(ab[3]),
- ],
- });
- }
- None => *unbounded.entry(k).or_default() += 1,
- }
- }
-
- println!("ββββ per type ββββββββββββββββββββββββββββββββββββββββββββββββ");
- println!(
- "{:<14} {:>6} {:>6} {:>6} {:>6} {:>10} {:>10}",
- "Type", "total", "idx", "unb", "skip", "top-lvl", "blk-int"
- );
- let mut all_keys: std::collections::BTreeSet<&str> = std::collections::BTreeSet::new();
- all_keys.extend(total.keys());
- for k in &all_keys {
- println!(
- "{:<14} {:>6} {:>6} {:>6} {:>6} {:>10} {:>10}",
- k,
- total.get(k).copied().unwrap_or(0),
- indexed.get(k).copied().unwrap_or(0),
- unbounded.get(k).copied().unwrap_or(0),
- unindexable_count.get(k).copied().unwrap_or(0),
- top_level.get(k).copied().unwrap_or(0),
- block_internal.get(k).copied().unwrap_or(0),
- );
- }
-
- println!();
- println!("union of indexed AABBs: {:?}", union);
-
- // Sample top-level entity bboxes by type
- println!();
- println!("ββββ sample top-level entity bboxes (first 5 per type) ββββββββ");
- let mut shown: BTreeMap<&str, usize> = BTreeMap::new();
- for e in doc.entities() {
- let k = entity_kind(e);
- if e.common().owner_handle != model_block {
- continue;
- }
- let c = shown.entry(k).or_insert(0);
- if *c >= 5 {
- continue;
- }
- *c += 1;
- let bb = e.as_entity().bounding_box();
- println!(
- " {:<12} h={:?} bb=({:.3},{:.3})β({:.3},{:.3})",
- k,
- e.common().handle,
- bb.min.x, bb.min.y, bb.max.x, bb.max.y,
- );
- }
-
- Ok(())
-}
diff --git a/examples/find_raster.rs b/examples/find_raster.rs
deleted file mode 100644
index af01c082..00000000
--- a/examples/find_raster.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use acadrust::entities::EntityType;
-use acadrust::io::dwg::DwgReader;
-fn main() -> Result<(), Box> {
- let path = std::env::args().nth(1).unwrap();
- let doc = DwgReader::from_file(&path)?.read()?;
- for e in doc.entities() {
- if let EntityType::RasterImage(img) = e {
- println!("file_path: {}", img.file_path);
- println!("size: {} x {}", img.size.x, img.size.y);
- if let Ok(meta) = std::fs::metadata(&img.file_path) { println!("disk size: {} bytes", meta.len()); }
- }
- }
- Ok(())
-}
diff --git a/examples/inspect_anno.rs b/examples/inspect_anno.rs
deleted file mode 100644
index f2102353..00000000
--- a/examples/inspect_anno.rs
+++ /dev/null
@@ -1,233 +0,0 @@
-// Inspect DIMSCALE, dimstyles, text heights, and xdata to diagnose
-// annotation-scale bugs in paper-space viewports.
-//
-// cargo run --release --example inspect_anno --
-
-use acadrust::entities::{Dimension, EntityType};
-use acadrust::io::dwg::DwgReader;
-
-fn main() -> Result<(), Box> {
- let path = std::env::args().nth(1).expect("usage: inspect_anno ");
- let doc = DwgReader::from_file(&path)?.read()?;
- println!("file: {}\n", path);
-
- println!("βββ header ββββββββββββββββββββββββββββββ");
- println!(" DIMSCALE (dim_scale) = {}", doc.header.dim_scale);
- println!(" DIMTXT (dim_text_height)= {}", doc.header.dim_text_height);
- println!(" DIMASZ (dim_arrow_size) = {}", doc.header.dim_arrow_size);
- println!(" TEXTSIZE (text_height) = {}", doc.header.text_height);
- println!(" LTSCALE = {}", doc.header.linetype_scale);
- println!(" PSLTSCALE (psls) = {}", doc.header.paper_space_linetype_scaling);
- println!(" CELTSCALE = {}", doc.header.current_entity_linetype_scale);
- println!(" viewport_scale_factor = {}", doc.header.viewport_scale_factor);
- println!();
- println!("βββ linetypes (first 10) ββββββββββββββββ");
- let mut shown = 0;
- for lt in doc.line_types.iter() {
- if shown >= 10 { break; }
- println!(
- " {:<24} pattern_len={:.4} elements={}",
- lt.name, lt.pattern_length, lt.elements.len()
- );
- shown += 1;
- }
- println!();
-
- println!("βββ dim_styles ββββββββββββββββββββββββββ");
- println!(
- " {:<24} {:>10} {:>10} {:>10} {:>10}",
- "name", "dimscale", "dimtxt", "dimasz", "dimexe"
- );
- for s in doc.dim_styles.iter() {
- println!(
- " {:<24} {:>10.4} {:>10.4} {:>10.4} {:>10.4}",
- s.name, s.dimscale, s.dimtxt, s.dimasz, s.dimexe
- );
- }
- println!();
-
- println!("βββ text_styles βββββββββββββββββββββββββ");
- for s in doc.text_styles.iter() {
- println!(
- " {:<24} height={:.4} last_height={:.4} font={:?}",
- s.name, s.height, s.last_height, s.font_file
- );
- }
- println!();
-
- let mut n_text = 0u32;
- let mut n_text_with_xdata = 0u32;
- let mut n_text_with_acanno = 0u32;
- let mut n_mtext = 0u32;
- let mut n_mtext_with_xdata = 0u32;
- let mut n_mtext_with_acanno = 0u32;
- let mut n_dim = 0u32;
- let mut n_dim_with_xdata = 0u32;
- let mut n_dim_with_acanno = 0u32;
- let mut xd_app_counts: std::collections::BTreeMap = Default::default();
-
- let mut sample_text_h: Vec = vec![];
- let mut sample_mtext_h: Vec = vec![];
- let mut sample_dim_style: std::collections::BTreeMap = Default::default();
- // For MTEXT: bucket by owner block name (paper vs model) and height range.
- let mut mtext_by_owner: std::collections::BTreeMap> = Default::default();
-
- let acanno_keys = ["AcAnnoPO", "AcAnnotativeData", "AcAnnoScaleObj", "AcDbXrecObject"];
-
- for e in doc.entities() {
- match e {
- EntityType::Text(t) => {
- n_text += 1;
- let xd = &t.common.extended_data;
- let has_xd = !xd.records().is_empty();
- if has_xd {
- n_text_with_xdata += 1;
- for r in xd.records() {
- *xd_app_counts.entry(r.application_name.clone()).or_default() += 1;
- }
- }
- if acanno_keys.iter().any(|k| xd.get_record(k).is_some()) {
- n_text_with_acanno += 1;
- }
- if sample_text_h.len() < 10 {
- sample_text_h.push(t.height);
- }
- }
- EntityType::MText(t) => {
- n_mtext += 1;
- let xd = &t.common.extended_data;
- let has_xd = !xd.records().is_empty();
- if has_xd {
- n_mtext_with_xdata += 1;
- for r in xd.records() {
- *xd_app_counts.entry(r.application_name.clone()).or_default() += 1;
- }
- }
- if acanno_keys.iter().any(|k| xd.get_record(k).is_some()) {
- n_mtext_with_acanno += 1;
- }
- if sample_mtext_h.len() < 10 {
- sample_mtext_h.push(t.height);
- }
- // Look up the owning block-record by handle and label as
- // "*Model_Space" / "*Paper_Space*" / "".
- let owner_h = t.common.owner_handle;
- let owner_label = doc
- .block_records
- .iter()
- .find_map(|br: &acadrust::BlockRecord| {
- if br.handle == owner_h {
- Some(br.name.clone())
- } else {
- None
- }
- })
- .unwrap_or_else(|| format!("h{}", owner_h.value()));
- mtext_by_owner
- .entry(owner_label)
- .or_default()
- .push(t.height);
- }
- EntityType::Dimension(d) => {
- n_dim += 1;
- let base = match d {
- Dimension::Aligned(d) => &d.base,
- Dimension::Linear(d) => &d.base,
- Dimension::Radius(d) => &d.base,
- Dimension::Diameter(d) => &d.base,
- Dimension::Angular2Ln(d) => &d.base,
- Dimension::Angular3Pt(d) => &d.base,
- Dimension::Ordinate(d) => &d.base,
- };
- let xd = &base.common.extended_data;
- let has_xd = !xd.records().is_empty();
- if has_xd {
- n_dim_with_xdata += 1;
- for r in xd.records() {
- *xd_app_counts.entry(r.application_name.clone()).or_default() += 1;
- }
- }
- if acanno_keys.iter().any(|k| xd.get_record(k).is_some()) {
- n_dim_with_acanno += 1;
- }
- *sample_dim_style.entry(base.style_name.clone()).or_default() += 1;
- }
- _ => {}
- }
- }
-
- println!("βββ annotation entity counts ββββββββββββ");
- println!(
- " TEXT total={:<5} xdata={:<5} AcAnno={}",
- n_text, n_text_with_xdata, n_text_with_acanno
- );
- println!(
- " MTEXT total={:<5} xdata={:<5} AcAnno={}",
- n_mtext, n_mtext_with_xdata, n_mtext_with_acanno
- );
- println!(
- " DIMENSION total={:<5} xdata={:<5} AcAnno={}",
- n_dim, n_dim_with_xdata, n_dim_with_acanno
- );
- println!();
-
- println!("βββ xdata application names seen ββββββββ");
- for (k, v) in &xd_app_counts {
- println!(" {:>5} {}", v, k);
- }
- println!();
-
- if !sample_text_h.is_empty() {
- println!("βββ first 10 TEXT heights βββββββββββββββ");
- for h in &sample_text_h {
- println!(" {:.4}", h);
- }
- println!();
- }
- if !sample_mtext_h.is_empty() {
- println!("βββ first 10 MTEXT heights ββββββββββββββ");
- for h in &sample_mtext_h {
- println!(" {:.4}", h);
- }
- println!();
- }
- if !mtext_by_owner.is_empty() {
- println!("βββ MTEXT by owner ββββββββββββββββββββββ");
- for (owner, heights) in &mtext_by_owner {
- let mut h = heights.clone();
- h.sort_by(|a, b| a.partial_cmp(b).unwrap());
- let min = h.first().copied().unwrap_or(0.0);
- let max = h.last().copied().unwrap_or(0.0);
- let median = h[h.len() / 2];
- let n_below_10 = h.iter().filter(|&&x| x < 10.0).count();
- let n_above_100 = h.iter().filter(|&&x| x > 100.0).count();
- println!(
- " {:<20} n={:<4} min={:.2} med={:.2} max={:.2} <10:{} >100:{}",
- owner,
- h.len(),
- min,
- median,
- max,
- n_below_10,
- n_above_100
- );
- }
- println!();
- }
-
- if !sample_dim_style.is_empty() {
- println!("βββ dimension styles used (count) βββββββ");
- for (k, v) in &sample_dim_style {
- let used_style = doc.dim_styles.iter().find(|s| s.name == *k);
- let ds = used_style.map(|s| s.dimscale).unwrap_or(f64::NAN);
- let dt = used_style.map(|s| s.dimtxt).unwrap_or(f64::NAN);
- let da = used_style.map(|s| s.dimasz).unwrap_or(f64::NAN);
- println!(
- " {:>5}Γ style=\"{}\" dimscale={:.4} dimtxt={:.4} dimasz={:.4}",
- v, k, ds, dt, da
- );
- }
- }
-
- Ok(())
-}
diff --git a/examples/inspect_block.rs b/examples/inspect_block.rs
deleted file mode 100644
index 1ce6a277..00000000
--- a/examples/inspect_block.rs
+++ /dev/null
@@ -1,128 +0,0 @@
-// List entities inside a named block, showing their layer + resolved linetype.
-//
-// cargo run --release --example inspect_block --
-
-use acadrust::entities::EntityType;
-use acadrust::io::dwg::DwgReader;
-
-fn main() -> Result<(), Box> {
- let path = std::env::args().nth(1).expect("usage: inspect_block [block]");
- let block_name = std::env::args().nth(2);
- let doc = DwgReader::from_file(&path)?.read()?;
-
- if block_name.is_none() {
- let mut blocks: Vec<_> = doc
- .block_records
- .iter()
- .map(|br| {
- let n = doc
- .entities()
- .filter(|e| e.common().owner_handle == br.handle)
- .count();
- (br.name.clone(), n)
- })
- .collect();
- blocks.sort_by_key(|(_, n)| std::cmp::Reverse(*n));
- println!("βββ top 30 blocks by entity count βββββββ");
- for (name, n) in blocks.iter().take(30) {
- println!(" {:>5} {}", n, name);
- }
- return Ok(());
- }
- let block_name = block_name.unwrap();
-
- // Find the block record by name.
- let br = doc
- .block_records
- .iter()
- .find(|br| br.name.eq_ignore_ascii_case(&block_name))
- .ok_or_else(|| format!("block '{}' not found", block_name))?;
-
- println!("block: \"{}\" handle={:?}", br.name, br.handle);
- println!();
-
- let mut counts: std::collections::BTreeMap<&'static str, u32> = Default::default();
- let mut sample_by_kind: std::collections::BTreeMap<&'static str, Vec> =
- Default::default();
-
- for e in doc.entities() {
- if e.common().owner_handle != br.handle {
- continue;
- }
- let kind: &'static str = match e {
- EntityType::Line(_) => "Line",
- EntityType::LwPolyline(_) => "LwPolyline",
- EntityType::Polyline(_) => "Polyline",
- EntityType::Polyline2D(_) => "Polyline2D",
- EntityType::Arc(_) => "Arc",
- EntityType::Circle(_) => "Circle",
- EntityType::Spline(_) => "Spline",
- EntityType::Ellipse(_) => "Ellipse",
- EntityType::Text(_) => "Text",
- EntityType::MText(_) => "MText",
- EntityType::Insert(_) => "Insert",
- EntityType::Hatch(_) => "Hatch",
- EntityType::Solid(_) => "Solid",
- _ => "Other",
- };
- *counts.entry(kind).or_default() += 1;
-
- let c = e.common();
- let extra = match e {
- EntityType::Insert(i) => format!(" β block=\"{}\"", i.block_name),
- _ => String::new(),
- };
- let line = format!(
- " [{:?}] layer=\"{}\" lt=\"{}\" lt_scale={:.4}{}",
- e.common().handle, c.layer, c.linetype, c.linetype_scale, extra
- );
- let bucket = sample_by_kind.entry(kind).or_default();
- if bucket.len() < 4 {
- bucket.push(line);
- }
- }
-
- println!("βββ entity counts in block ββββββββββββββ");
- for (k, v) in &counts {
- println!(" {:<12} {}", k, v);
- }
- println!();
- for (k, samples) in &sample_by_kind {
- println!("βββ sample {} (first {}) ββββββββ", k, samples.len());
- for s in samples {
- println!("{}", s);
- }
- println!();
- }
-
- println!("βββ relevant layers βββββββββββββββββββββ");
- let mut seen: std::collections::BTreeSet = Default::default();
- for e in doc.entities() {
- if e.common().owner_handle == br.handle {
- seen.insert(e.common().layer.clone());
- }
- }
- for layer_name in &seen {
- if let Some(l) = doc.layers.get(layer_name) {
- println!(
- " \"{}\" lt=\"{}\" off={} frozen={}",
- l.name, l.line_type, l.flags.off, l.flags.frozen
- );
- }
- }
-
- println!();
- println!("βββ linetype table (dashed only) ββββββββ");
- for lt in doc.line_types.iter() {
- if lt.elements.is_empty() || lt.is_continuous() {
- continue;
- }
- let elems: Vec = lt.elements.iter().map(|el| el.length).collect();
- println!(
- " {:<24} pattern_len={:.4} elements={:?}",
- lt.name, lt.pattern_length, elems
- );
- }
-
- Ok(())
-}
diff --git a/examples/inspect_insert.rs b/examples/inspect_insert.rs
deleted file mode 100644
index e36437c2..00000000
--- a/examples/inspect_insert.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-// Lists every Insert in the doc (after xref resolve) with sub-entity counts.
-// cargo run --release --example inspect_insert --
-use acadrust::entities::EntityType;
-use acadrust::io::dwg::DwgReader;
-
-fn main() -> Result<(), Box> {
- let path = std::env::args().nth(1).unwrap();
- let mut doc = DwgReader::from_file(&path)?.read()?;
- if let Some(base) = std::path::Path::new(&path).parent() {
- let infos = H7CAD::io::xref::resolve_xrefs(&mut doc, base);
- for i in &infos {
- println!("XREF: {} -> {:?}", i.name, i.status);
- }
- }
- println!("total entities: {}", doc.entities().count());
-
- let inserts: Vec<_> = doc
- .entities()
- .filter_map(|e| if let EntityType::Insert(i) = e { Some(i.clone()) } else { None })
- .collect();
- println!("total inserts: {}", inserts.len());
-
- let mut by_block: std::collections::HashMap = std::collections::HashMap::new();
- for i in &inserts {
- *by_block.entry(i.block_name.clone()).or_insert(0) += 1;
- }
- let mut by_block: Vec<_> = by_block.into_iter().collect();
- by_block.sort_by(|a, b| b.1.cmp(&a.1));
-
- println!("\ninserts grouped by block_name:");
- for (name, n) in &by_block {
- let sub_count = inserts.iter().find(|i| &i.block_name == name)
- .map(|i| i.explode_from_document(&doc).len())
- .unwrap_or(0);
- let nested = doc.block_records.get(name)
- .map(|br| br.entity_handles.iter()
- .filter(|h| matches!(doc.get_entity(**h), Some(EntityType::Insert(_))))
- .count())
- .unwrap_or(0);
- println!(" {:>4} Γ {} (sub={}, nested-inserts={})", n, name, sub_count, nested);
- }
- Ok(())
-}
diff --git a/examples/inspect_lt.rs b/examples/inspect_lt.rs
deleted file mode 100644
index f87c1444..00000000
--- a/examples/inspect_lt.rs
+++ /dev/null
@@ -1,116 +0,0 @@
-// Summarise linetype usage in a DWG/DXF: which layers use which linetype,
-// and which entities carry an explicit (non-bylayer) dashed linetype.
-//
-// cargo run --release --example inspect_lt --
-
-use acadrust::entities::EntityType;
-use acadrust::io::dwg::DwgReader;
-use std::collections::BTreeMap;
-
-fn main() -> Result<(), Box> {
- let path = std::env::args().nth(1).expect("usage: inspect_lt ");
- let doc = DwgReader::from_file(&path)?.read()?;
-
- println!("βββ layers (linetype) βββββββββββββββββββ");
- let dashed_lts: std::collections::BTreeSet = doc
- .line_types
- .iter()
- .filter(|lt| !lt.elements.is_empty() && !lt.is_continuous())
- .map(|lt| lt.name.clone())
- .collect();
- println!(" dashed linetypes in table: {:?}", dashed_lts);
- println!();
-
- let mut dashed_layers: BTreeMap = BTreeMap::new();
- for l in doc.layers.iter() {
- if dashed_lts.contains(&l.line_type) {
- dashed_layers.insert(l.name.clone(), l.line_type.clone());
- }
- }
- println!(" layers using a dashed linetype:");
- if dashed_layers.is_empty() {
- println!(" (none)");
- }
- for (n, lt) in &dashed_layers {
- println!(" \"{}\" β \"{}\"", n, lt);
- }
- println!();
-
- // Per-entity explicit dashed override (lt field non-empty and non-byLayer/byBlock/Continuous).
- let mut explicit_dashed: u32 = 0;
- let mut by_layer_in_dashed_layer: u32 = 0;
- let mut by_layer_in_continuous: u32 = 0;
- let mut by_kind: BTreeMap<&'static str, u32> = BTreeMap::new();
- let mut sample_explicit: Vec = vec![];
- let mut sample_layer_inh: Vec = vec![];
-
- for e in doc.entities() {
- let c = e.common();
- let kind: &'static str = match e {
- EntityType::Line(_) => "Line",
- EntityType::LwPolyline(_) => "LwPolyline",
- EntityType::Polyline(_) => "Polyline",
- EntityType::Polyline2D(_) => "Polyline2D",
- EntityType::Arc(_) => "Arc",
- EntityType::Circle(_) => "Circle",
- EntityType::Spline(_) => "Spline",
- EntityType::Ellipse(_) => "Ellipse",
- EntityType::Insert(_) => "Insert",
- _ => "Other",
- };
- let lt = c.linetype.trim();
- let lt_norm = lt.to_ascii_lowercase();
- let is_bylayer = lt.is_empty() || lt_norm == "bylayer";
- let is_explicit_dashed = !is_bylayer
- && lt_norm != "byblock"
- && lt_norm != "continuous"
- && dashed_lts.iter().any(|d| d.eq_ignore_ascii_case(lt));
- if is_explicit_dashed {
- explicit_dashed += 1;
- *by_kind.entry(kind).or_default() += 1;
- if sample_explicit.len() < 6 {
- sample_explicit.push(format!(
- " [{:?}] {} layer=\"{}\" lt=\"{}\" lt_scale={:.4}",
- c.handle, kind, c.layer, lt, c.linetype_scale
- ));
- }
- } else if is_bylayer && dashed_layers.contains_key(&c.layer) {
- by_layer_in_dashed_layer += 1;
- if sample_layer_inh.len() < 6 {
- sample_layer_inh.push(format!(
- " [{:?}] {} layer=\"{}\" (inherits \"{}\") lt_scale={:.4}",
- c.handle,
- kind,
- c.layer,
- dashed_layers.get(&c.layer).unwrap(),
- c.linetype_scale
- ));
- }
- } else if is_bylayer {
- by_layer_in_continuous += 1;
- }
- }
-
- println!("βββ entities w/ explicit dashed lt ββββββ");
- println!(" total: {}", explicit_dashed);
- for (k, v) in &by_kind {
- println!(" {}: {}", k, v);
- }
- for s in &sample_explicit {
- println!("{}", s);
- }
- println!();
-
- println!("βββ entities inheriting dashed via layer:");
- println!(" total: {}", by_layer_in_dashed_layer);
- for s in &sample_layer_inh {
- println!("{}", s);
- }
- println!();
- println!(
- "βββ entities bylayer/continuous: {}",
- by_layer_in_continuous
- );
-
- Ok(())
-}
diff --git a/examples/inspect_polyline.rs b/examples/inspect_polyline.rs
deleted file mode 100644
index bd5994f5..00000000
--- a/examples/inspect_polyline.rs
+++ /dev/null
@@ -1,174 +0,0 @@
-// One-off inspector for diagnosing a DWG: dumps every LwPolyline/Polyline2D/
-// Polyline3D with its elevation, normal vector, and per-vertex coordinates.
-// Run with: cargo run --example inspect_polyline --
-
-use acadrust::entities::EntityType;
-use acadrust::io::dwg::DwgReader;
-use acadrust::DxfReader;
-use std::env;
-
-fn main() -> Result<(), Box> {
- let path = env::args().nth(1).ok_or("usage: inspect_polyline ")?;
- let mut doc = if path.to_lowercase().ends_with(".dxf") {
- DxfReader::from_file(&path)?.read()?
- } else {
- DwgReader::from_file(&path)?.read()?
- };
-
- // Cheap inline corruption check β mirrors the rules in src/io/mod.rs so the
- // example reports the same drop count without needing a library crate.
- let total = doc.entities().count();
- let bad = doc
- .entities()
- .filter(|e| {
- use acadrust::entities::EntityType as E;
- const MAX: usize = 100_000;
- let bad_normal = |n: &acadrust::types::Vector3| {
- !n.x.is_finite()
- || !n.y.is_finite()
- || !n.z.is_finite()
- || ((n.x * n.x + n.y * n.y + n.z * n.z) - 1.0).abs() >= 0.21
- };
- match e {
- E::LwPolyline(p) => {
- bad_normal(&p.normal)
- || p.vertices.len() > MAX
- || !p.elevation.is_finite()
- || p.elevation.abs() > 1e10
- }
- E::Polyline2D(p) => {
- bad_normal(&p.normal)
- || p.vertices.len() > MAX
- || !p.elevation.is_finite()
- || p.elevation.abs() > 1e10
- }
- _ => false,
- }
- })
- .count();
- println!("Entities: total={} corrupt={}", total, bad);
- println!();
- let _ = &mut doc; // silence unused-mut warning if we don't mutate below
-
- let h = &doc.header;
- println!(
- "Header extents: min=({:.3},{:.3},{:.3}) max=({:.3},{:.3},{:.3})",
- h.model_space_extents_min.x,
- h.model_space_extents_min.y,
- h.model_space_extents_min.z,
- h.model_space_extents_max.x,
- h.model_space_extents_max.y,
- h.model_space_extents_max.z,
- );
- println!();
-
- let mut lwp = 0usize;
- let mut p2d = 0usize;
- let mut p3d = 0usize;
- let mut pl = 0usize;
-
- for (i, e) in doc.entities().enumerate() {
- match e {
- EntityType::LwPolyline(p) => {
- lwp += 1;
- if p.common.layer != "PLN_Sev" {
- continue;
- }
- let nx_abs = p.normal.x.abs();
- let ny_abs = p.normal.y.abs();
- let corrupt = !nx_abs.is_finite()
- || nx_abs > 1.0
- || ny_abs > 1.0
- || p.vertices.len() > 1000;
- if corrupt {
- println!(
- "[{}] CORRUPT handle={:?} verts={} elev={:.3e} normal=({:.2e},{:.2e},{:.2e})",
- i,
- p.common.handle,
- p.vertices.len(),
- p.elevation,
- p.normal.x,
- p.normal.y,
- p.normal.z,
- );
- } else {
- println!(
- "[{}] OK handle={:?} verts={} elev={:.3} normal=({:.4},{:.4},{:.4})",
- i,
- p.common.handle,
- p.vertices.len(),
- p.elevation,
- p.normal.x,
- p.normal.y,
- p.normal.z,
- );
- for (vi, v) in p.vertices.iter().take(3).enumerate() {
- println!(" v{}: ({:.3}, {:.3}) bulge={}", vi, v.location.x, v.location.y, v.bulge);
- }
- }
- }
- EntityType::Polyline2D(p) => {
- p2d += 1;
- if p2d <= 5 {
- println!(
- "[{}] Polyline2D handle={:?} layer={:?}",
- i, p.common.handle, p.common.layer
- );
- println!(
- " elevation={} thickness={} normal=({},{},{})",
- p.elevation, p.thickness, p.normal.x, p.normal.y, p.normal.z
- );
- println!(" closed={} verts={}", p.is_closed(), p.vertices.len());
- for (vi, v) in p.vertices.iter().enumerate() {
- println!(
- " v{}: ({}, {}, {}) bulge={}",
- vi, v.location.x, v.location.y, v.location.z, v.bulge
- );
- }
- println!();
- }
- }
- EntityType::Polyline3D(p) => {
- p3d += 1;
- if p3d <= 5 {
- println!(
- "[{}] Polyline3D handle={:?} layer={:?}",
- i, p.common.handle, p.common.layer
- );
- println!(" closed={} verts={}", p.is_closed(), p.vertices.len());
- for (vi, v) in p.vertices.iter().enumerate() {
- println!(
- " v{}: ({}, {}, {})",
- vi, v.position.x, v.position.y, v.position.z
- );
- }
- println!();
- }
- }
- EntityType::Polyline(p) => {
- pl += 1;
- if pl <= 5 {
- println!(
- "[{}] Polyline (heavy 3D) handle={:?} layer={:?}",
- i, p.common.handle, p.common.layer
- );
- println!(" closed={} verts={}", p.flags.is_closed(), p.vertices.len());
- for (vi, v) in p.vertices.iter().enumerate() {
- println!(
- " v{}: ({}, {}, {})",
- vi, v.location.x, v.location.y, v.location.z
- );
- }
- println!();
- }
- }
- _ => {}
- }
- }
-
- println!(
- "Totals: LwPolyline={} Polyline2D={} Polyline3D={} Polyline={}",
- lwp, p2d, p3d, pl
- );
- Ok(())
-}
diff --git a/examples/inspect_viewports.rs b/examples/inspect_viewports.rs
deleted file mode 100644
index 328c5e0d..00000000
--- a/examples/inspect_viewports.rs
+++ /dev/null
@@ -1,126 +0,0 @@
-// Dumps every paper-space viewport's view fields from a DWG/DXF.
-// cargo run --release --example inspect_viewports --
-use acadrust::entities::EntityType;
-use acadrust::io::dwg::DwgReader;
-
-fn main() -> Result<(), Box> {
- let path = std::env::args().nth(1).expect("usage: inspect_viewports ");
- let doc = DwgReader::from_file(&path)?.read()?;
- println!("file: {}", path);
- println!("total entities: {}", doc.entities().count());
- let unit_name = match doc.header.insertion_units {
- 0 => "Unitless",
- 1 => "Inches",
- 2 => "Feet",
- 3 => "Miles",
- 4 => "Millimeters",
- 5 => "Centimeters",
- 6 => "Meters",
- 7 => "Kilometers",
- _ => "Other",
- };
- println!(
- "header.insertion_units = {} ({})",
- doc.header.insertion_units, unit_name
- );
- println!(
- "header.model_space_extents min=({:.3}, {:.3}, {:.3}) max=({:.3}, {:.3}, {:.3})",
- doc.header.model_space_extents_min.x,
- doc.header.model_space_extents_min.y,
- doc.header.model_space_extents_min.z,
- doc.header.model_space_extents_max.x,
- doc.header.model_space_extents_max.y,
- doc.header.model_space_extents_max.z,
- );
- println!();
-
- let viewports: Vec<_> = doc
- .entities()
- .filter_map(|e| {
- if let EntityType::Viewport(v) = e {
- Some(v.clone())
- } else {
- None
- }
- })
- .collect();
- println!("viewports: {}\n", viewports.len());
-
- for (i, vp) in viewports.iter().enumerate() {
- let scale_from_view_height = if vp.view_height.abs() > 1e-9 {
- vp.height / vp.view_height
- } else {
- f64::NAN
- };
- println!(
- "[{}] id={} handle={:?}",
- i, vp.id, vp.common.handle
- );
- println!(
- " paper center=({:.3}, {:.3}) size={:.3} Γ {:.3}",
- vp.center.x, vp.center.y, vp.width, vp.height
- );
- println!(
- " view_target=({:.3}, {:.3}, {:.3})",
- vp.view_target.x, vp.view_target.y, vp.view_target.z
- );
- println!(
- " view_direction=({:.3}, {:.3}, {:.3})",
- vp.view_direction.x, vp.view_direction.y, vp.view_direction.z
- );
- println!(
- " view_center=({:.3}, {:.3})",
- vp.view_center.x, vp.view_center.y
- );
- println!(
- " view_height={:.6} == vp.height? {} β height/view_height = {:.6}",
- vp.view_height,
- (vp.view_height - vp.height).abs() < 1e-6,
- scale_from_view_height
- );
- println!(
- " custom_scale={:.6} twist={:.4} lens={:.2}",
- vp.custom_scale, vp.twist_angle, vp.lens_length
- );
- println!(
- " status: on={}, locked={}, perspective={}",
- vp.status.is_on, vp.status.locked, vp.status.perspective
- );
- println!();
- }
-
- // Summary stats
- let n_with_view_eq_height = viewports
- .iter()
- .filter(|v| (v.view_height - v.height).abs() < 1e-6)
- .count();
- let n_with_target_zero = viewports
- .iter()
- .filter(|v| {
- v.view_target.x.abs() < 1e-9
- && v.view_target.y.abs() < 1e-9
- && v.view_target.z.abs() < 1e-9
- })
- .count();
- let unique_view_heights: std::collections::BTreeSet = viewports
- .iter()
- .map(|v| v.view_height.to_bits())
- .collect();
-
- println!("βββββββ summary βββββββ");
- println!(
- " view_height == vp.height : {}/{}",
- n_with_view_eq_height,
- viewports.len()
- );
- println!(
- " view_target == (0, 0, 0) : {}/{}",
- n_with_target_zero,
- viewports.len()
- );
- println!(
- " unique view_height values : {}",
- unique_view_heights.len()
- );
- Ok(())
-}
diff --git a/examples/time_open.rs b/examples/time_open.rs
deleted file mode 100644
index bba5940e..00000000
--- a/examples/time_open.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-// Times each open phase: parse / purge / derived caches.
-// Run with: cargo run --release --example time_open --
-
-use acadrust::entities::EntityType;
-use std::env;
-use std::path::Path;
-use std::time::Instant;
-use H7CAD::io::{load_file, purge_corrupt_entities};
-use H7CAD::scene::{build_derived_caches, Scene};
-
-fn main() -> Result<(), Box> {
- let path = env::args().nth(1).ok_or("usage: time_open ")?;
-
- let t0 = Instant::now();
- let mut doc = load_file(Path::new(&path))?;
- let parse_ms = t0.elapsed().as_millis();
-
- let t1 = Instant::now();
- let dropped = purge_corrupt_entities(&mut doc);
- let purge_ms = t1.elapsed().as_millis();
-
- let t2 = Instant::now();
- let caches = build_derived_caches(&doc);
- let caches_ms = t2.elapsed().as_millis();
-
- let mut counts = std::collections::HashMap::<&'static str, usize>::new();
- let mut total = 0usize;
- for e in doc.entities() {
- total += 1;
- let tag: &'static str = match e {
- EntityType::Line(_) => "Line",
- EntityType::Arc(_) => "Arc",
- EntityType::Circle(_) => "Circle",
- EntityType::LwPolyline(_) => "LwPolyline",
- EntityType::Polyline2D(_) => "Polyline2D",
- EntityType::Polyline3D(_) => "Polyline3D",
- EntityType::Polyline(_) => "Polyline",
- EntityType::Hatch(_) => "Hatch",
- EntityType::Solid(_) => "Solid",
- EntityType::RasterImage(_) => "RasterImage",
- EntityType::Solid3D(_) => "Solid3D",
- EntityType::Region(_) => "Region",
- EntityType::Body(_) => "Body",
- EntityType::Text(_) => "Text",
- EntityType::MText(_) => "MText",
- EntityType::Insert(_) => "Insert",
- EntityType::Dimension(_) => "Dimension",
- EntityType::Spline(_) => "Spline",
- EntityType::Ellipse(_) => "Ellipse",
- _ => "_other",
- };
- *counts.entry(tag).or_insert(0) += 1;
- }
- let mut counts: Vec<_> = counts.into_iter().collect();
- counts.sort_by(|a, b| b.1.cmp(&a.1));
-
- // Set up a Scene as the UI thread does and time first wire tessellation.
- let mut scene = Scene::new();
- scene.document = doc;
- scene.world_offset = caches.world_offset;
- scene.local_extent_max = caches.local_extent_max;
- scene.hatches = caches.hatches.clone();
- scene.images = caches.images.clone();
- scene.meshes = caches.meshes.clone();
- scene.bump_geometry();
- scene.current_layout = "Model".to_string();
- H7CAD::linetypes::populate_document(&mut scene.document);
-
- let t3 = Instant::now();
- let wires = scene.entity_wires();
- let wires_ms = t3.elapsed().as_millis();
-
- println!("file: {}", path);
- println!("parse: {} ms", parse_ms);
- println!("purge: {} ms (dropped {})", purge_ms, dropped);
- println!("derived caches: {} ms", caches_ms);
- println!("first wires: {} ms ({} wires)", wires_ms, wires.len());
- println!(" hatches: {}", caches.hatches.len());
- println!(" images: {}", caches.images.len());
- println!(" meshes: {}", caches.meshes.len());
- println!();
- println!("entities: {}", total);
- for (tag, n) in counts.iter().take(20) {
- println!(" {:>14} {}", tag, n);
- }
- Ok(())
-}
diff --git a/examples/xref_states.rs b/examples/xref_states.rs
deleted file mode 100644
index dff5252a..00000000
--- a/examples/xref_states.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Dump every xref block_record's raw is_loaded bit before any resolve.
-// cargo run --release --example xref_states --
-use acadrust::io::dwg::DwgReader;
-
-fn main() -> Result<(), Box> {
- let path = std::env::args().nth(1).unwrap();
- let doc = DwgReader::from_file(&path)?.read()?;
-
- for br in doc.block_records.iter() {
- if br.flags.is_xref || br.flags.is_xref_overlay {
- println!(
- "name={:<30} is_xref={} overlay={} is_loaded={:?} xref_path={:?} entity_handles={}",
- br.name,
- br.flags.is_xref,
- br.flags.is_xref_overlay,
- br.is_loaded,
- br.xref_path,
- br.entity_handles.len(),
- );
- }
- }
- Ok(())
-}
diff --git a/packaging/Info.plist b/packaging/Info.plist
index bfd271df..a7f7913f 100644
--- a/packaging/Info.plist
+++ b/packaging/Info.plist
@@ -5,17 +5,17 @@
CFBundleDevelopmentRegion
en
CFBundleDisplayName
- H7CAD
+ Open CAD Studio
CFBundleExecutable
- H7CAD
+ OpenCADStudio
CFBundleIconFile
AppIcon
CFBundleIdentifier
- io.github.HakanSeven12.H7CAD
+ io.github.HakanSeven12.OpenCadStudio
CFBundleInfoDictionaryVersion
6.0
CFBundleName
- H7CAD
+ Open CAD Studio
CFBundlePackageType
APPL
CFBundleShortVersionString
diff --git a/packaging/H7CAD.desktop b/packaging/OpenCADStudio.desktop
similarity index 65%
rename from packaging/H7CAD.desktop
rename to packaging/OpenCADStudio.desktop
index bdc9a433..6b9fe993 100644
--- a/packaging/H7CAD.desktop
+++ b/packaging/OpenCADStudio.desktop
@@ -1,11 +1,11 @@
[Desktop Entry]
-Name=H7CAD
+Name=Open CAD Studio
Comment=A CAD application for 2D/3D drawing and design
-Exec=H7CAD
-Icon=io.github.HakanSeven12.H7CAD
+Exec=OpenCADStudio
+Icon=io.github.HakanSeven12.OpenCadStudio
Terminal=false
Type=Application
Categories=Graphics;Engineering;
MimeType=image/vnd.dxf;
Keywords=CAD;DXF;drawing;design;engineering;2D;3D;
-StartupWMClass=H7CAD
+StartupWMClass=OpenCADStudio
diff --git a/src/app/cmd_result.rs b/src/app/cmd_result.rs
index 81ae0674..e2732699 100644
--- a/src/app/cmd_result.rs
+++ b/src/app/cmd_result.rs
@@ -1,9 +1,9 @@
-use super::{Message, H7CAD};
+use super::{Message, OpenCADStudio};
use crate::command::CmdResult;
use acadrust::Handle;
use iced::Task;
-impl H7CAD {
+impl OpenCADStudio {
pub(super) fn apply_cmd_result(&mut self, result: CmdResult) -> Task {
let i = self.active_tab;
match result {
diff --git a/src/app/commands.rs b/src/app/commands.rs
index 41e3e1b2..8736e748 100644
--- a/src/app/commands.rs
+++ b/src/app/commands.rs
@@ -1,10 +1,10 @@
-use super::{Message, H7CAD};
+use super::{Message, OpenCADStudio};
use crate::command::CadCommand;
use crate::scene::Scene;
use iced::Task;
use std::path::PathBuf;
-impl H7CAD {
+impl OpenCADStudio {
pub(super) fn dispatch_command(&mut self, cmd: &str) -> Task {
let i = self.active_tab;
// Cancel any running command before starting a new one.
@@ -2524,7 +2524,7 @@ impl H7CAD {
}
"REPORT" => {
- let _ = open::that("https://github.com/HakanSeven12/H7CAD/issues/new");
+ let _ = open::that("https://github.com/HakanSeven12/open-cad-studio/issues/new");
self.command_line.push_info("Opening GitHub issue page...");
}
@@ -2533,7 +2533,7 @@ impl H7CAD {
}
"CHANGELOG" => {
- let _ = open::that("https://github.com/HakanSeven12/H7CAD/releases");
+ let _ = open::that("https://github.com/HakanSeven12/open-cad-studio/releases");
self.command_line.push_info("Opening release notes...");
}
@@ -4831,7 +4831,7 @@ impl H7CAD {
}
}
"SET" => {
- let app = parts.get(1).copied().unwrap_or("H7CAD");
+ let app = parts.get(1).copied().unwrap_or("OpenCADStudio");
let val = parts.get(2).copied().unwrap_or("");
self.push_undo_snapshot(i, "XDATA SET");
for sh in &selected_handles {
diff --git a/src/app/helpers.rs b/src/app/helpers.rs
index 00e64f6f..e712a5da 100644
--- a/src/app/helpers.rs
+++ b/src/app/helpers.rs
@@ -229,7 +229,7 @@ pub(super) fn title_case_word(value: &str) -> String {
// ββ Window icon ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-/// Builds a 32Γ32 RGBA icon: red background with H7 drawn in white pixels.
+/// Builds a 32Γ32 RGBA icon: red background with OCS drawn in white pixels.
pub(super) fn build_window_icon() -> Vec {
const W: usize = 32;
const SZ: usize = W * W * 4;
@@ -261,14 +261,21 @@ pub(super) fn build_window_icon() -> Vec {
}
}
- // H
- stroke(&mut px, 4, 5, 4, 26, fg);
- stroke(&mut px, 13, 5, 13, 26, fg);
- stroke(&mut px, 4, 15, 13, 15, fg);
- // 7
- stroke(&mut px, 17, 5, 27, 5, fg);
- stroke(&mut px, 27, 5, 20, 26, fg);
- stroke(&mut px, 20, 16, 26, 16, fg);
+ // O
+ stroke(&mut px, 3, 6, 9, 6, fg);
+ stroke(&mut px, 3, 25, 9, 25, fg);
+ stroke(&mut px, 3, 6, 3, 25, fg);
+ stroke(&mut px, 9, 6, 9, 25, fg);
+ // C
+ stroke(&mut px, 12, 6, 18, 6, fg);
+ stroke(&mut px, 12, 25, 18, 25, fg);
+ stroke(&mut px, 12, 6, 12, 25, fg);
+ // S
+ stroke(&mut px, 21, 6, 27, 6, fg);
+ stroke(&mut px, 21, 6, 21, 15, fg);
+ stroke(&mut px, 21, 15, 27, 15, fg);
+ stroke(&mut px, 27, 15, 27, 25, fg);
+ stroke(&mut px, 21, 25, 27, 25, fg);
px
}
diff --git a/src/app/history.rs b/src/app/history.rs
index 9e3b5d3e..5d22b83b 100644
--- a/src/app/history.rs
+++ b/src/app/history.rs
@@ -1,7 +1,7 @@
-use super::{document::HistorySnapshot, H7CAD};
+use super::{document::HistorySnapshot, OpenCADStudio};
use std::collections::HashSet;
-impl H7CAD {
+impl OpenCADStudio {
pub(super) fn history_label_from_active_cmd(&self, i: usize, fallback: &'static str) -> String {
self.tabs[i]
.active_cmd
diff --git a/src/app/layers.rs b/src/app/layers.rs
index b0b193f0..e914bcf2 100644
--- a/src/app/layers.rs
+++ b/src/app/layers.rs
@@ -1,7 +1,7 @@
-use super::H7CAD;
+use super::OpenCADStudio;
use crate::ui;
-impl H7CAD {
+impl OpenCADStudio {
pub(super) fn sync_ribbon_layers(&mut self) {
let i = self.active_tab;
let active = self.tabs[i].active_layer.clone();
diff --git a/src/app/mod.rs b/src/app/mod.rs
index fb2a5467..24861433 100644
--- a/src/app/mod.rs
+++ b/src/app/mod.rs
@@ -44,7 +44,7 @@ pub struct OpenProgress {
// ββ Application state ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-pub(super) struct H7CAD {
+pub(super) struct OpenCADStudio {
start: Instant,
tabs: Vec,
active_tab: usize,
@@ -697,7 +697,7 @@ pub enum Message {
ObjImportPath(Option),
}
-impl H7CAD {
+impl OpenCADStudio {
fn new() -> Self {
// Boot with only the Welcome/Start tab. The user creates drawings
// explicitly (File β New); we never auto-spawn Drawing1.
@@ -855,9 +855,9 @@ impl H7CAD {
use std::path::PathBuf;
pub fn run() -> iced::Result {
- iced::daemon(H7CAD::boot, H7CAD::update, H7CAD::view)
- .subscription(H7CAD::subscription)
- .title(|state: &H7CAD, window_id: window::Id| {
+ iced::daemon(OpenCADStudio::boot, OpenCADStudio::update, OpenCADStudio::view)
+ .subscription(OpenCADStudio::subscription)
+ .title(|state: &OpenCADStudio, window_id: window::Id| {
if Some(window_id) == state.layer_window {
return "Layer Properties Manager".into();
}
@@ -886,7 +886,7 @@ pub fn run() -> iced::Result {
return "Keyboard Shortcuts".into();
}
if Some(window_id) == state.about_window {
- return "About H7CAD".into();
+ return "About Open CAD Studio".into();
}
if Some(window_id) == state.update_notice_window {
return "Update Available".into();
@@ -900,11 +900,11 @@ pub fn run() -> iced::Result {
if let Some(tab) = state.tabs.get(state.active_tab) {
let dot = if tab.dirty { "β " } else { "" };
let name = tab.tab_display_name();
- format!("{}H7CAD β {}", dot, name)
+ format!("{}Open CAD Studio β {}", dot, name)
} else {
- "H7CAD".to_string()
+ "Open CAD Studio".to_string()
}
})
- .theme(|state: &H7CAD, _| state.active_theme.clone())
+ .theme(|state: &OpenCADStudio, _| state.active_theme.clone())
.run()
}
diff --git a/src/app/properties.rs b/src/app/properties.rs
index a8080ef5..8aeaba4f 100644
--- a/src/app/properties.rs
+++ b/src/app/properties.rs
@@ -1,11 +1,11 @@
use super::helpers::{entity_type_key, entity_type_label, title_case_word};
-use super::{H7CAD, VARIES_LABEL};
+use super::{OpenCADStudio, VARIES_LABEL};
use crate::linetypes;
use crate::scene::dispatch;
use crate::ui;
use acadrust::{EntityType, Handle};
-impl H7CAD {
+impl OpenCADStudio {
/// Rebuild the PropertiesPanel from the current entity selection.
/// Preserves UI state (open pickers, edit buffer) across refreshes.
pub(super) fn refresh_properties(&mut self) {
diff --git a/src/app/update.rs b/src/app/update.rs
index 50407af0..56bdb622 100644
--- a/src/app/update.rs
+++ b/src/app/update.rs
@@ -1,7 +1,7 @@
use super::helpers::{
angle_close, ortho_constrain, parse_coord, polar_constrain, ucs_to_wcs, ucs_z_axis,
};
-use super::{Message, H7CAD, POLY_START_DELAY_MS};
+use super::{Message, OpenCADStudio, POLY_START_DELAY_MS};
use crate::modules::ModuleEvent;
use crate::scene::grip::{find_hit_grip, find_hit_grip_paper, GripEdit};
use crate::scene::object::GripApply;
@@ -31,7 +31,7 @@ fn format_size(bytes: u64) -> String {
}
}
-impl H7CAD {
+impl OpenCADStudio {
pub fn update(&mut self, msg: Message) -> Task {
match msg {
Message::Tick(t) => {
@@ -3414,7 +3414,7 @@ impl H7CAD {
Message::AboutCopyInfo => {
let info = format!(
- "H7CAD v{}\nOS: {}\nArch: {}",
+ "Open CAD Studio v{}\nOS: {}\nArch: {}",
env!("CARGO_PKG_VERSION"),
std::env::consts::OS,
std::env::consts::ARCH,
@@ -4826,7 +4826,7 @@ impl H7CAD {
// ββ DimStyle dialog helpers βββββββββββββββββββββββββββββββββββββββββββββββββ
-impl H7CAD {
+impl OpenCADStudio {
/// Populate all edit buffers from the currently selected dim style.
fn load_dimstyle_bufs(&mut self, tab: usize) {
let doc = &self.tabs[tab].scene.document;
diff --git a/src/app/view.rs b/src/app/view.rs
index 9e648c06..c758e146 100644
--- a/src/app/view.rs
+++ b/src/app/view.rs
@@ -1,7 +1,7 @@
use super::document::DocumentTab;
use super::helpers::grid_plane_from_camera;
use super::history::history_dropdown_labels;
-use super::{Message, H7CAD};
+use super::{Message, OpenCADStudio};
use crate::scene::grip::{grips_to_screen, grips_to_screen_paper};
use crate::scene::paper_canvas::PaperCanvas;
use crate::scene::viewport_pane::{PaperViewportPane, ViewportPane};
@@ -16,7 +16,7 @@ use iced::{keyboard, Background, Border, Color, Element, Fill, Subscription, Tas
const VIEWCUBE_HIT_SIZE: f32 = VIEWCUBE_DRAW_PX;
-impl H7CAD {
+impl OpenCADStudio {
pub fn view(&self, window_id: window::Id) -> Element<'_, Message> {
// ββ Floating panel windows βββββββββββββββββββββββββββββββββββββββββ
if Some(window_id) == self.layer_window {
@@ -1594,7 +1594,7 @@ fn unsaved_changes_dialog_window(name: &str) -> Element<'static, Message> {
// is the public welcome screen and stays consistent across locales.
//
// The page picks up the application icon's red-brown (#B03020) as a tint so
-// it visually belongs to H7CAD without overpowering the dark workspace.
+// it visually belongs to OpenCADStudio without overpowering the dark workspace.
const BRAND: Color = Color { r: 0.690, g: 0.188, b: 0.125, a: 1.0 }; // #B03020
const BRAND_DARK: Color = Color { r: 0.45, g: 0.12, b: 0.08, a: 1.0 };
@@ -1605,16 +1605,16 @@ pub(super) fn start_page_view<'a>() -> Element<'a, Message> {
const CARD_BG: Color = Color { r: 0.12, g: 0.12, b: 0.13, a: 1.0 };
const CARD_BORDER: Color = Color { r: 0.20, g: 0.20, b: 0.22, a: 1.0 };
- // Brand-tinted "Welcome to" β the "H7CAD" word takes the accent colour
+ // Brand-tinted "Welcome to" β the "OpenCADStudio" word takes the accent colour
// (Thunderbird-style coloured headline split).
let headline = row![
text("Welcome to ").size(40).color(TEXT),
- text("H7CAD").size(40).color(BRAND),
+ text("Open CAD Studio").size(40).color(BRAND),
]
.align_y(iced::Center);
let subtitle = text(
- "H7CAD is an open-source CAD viewer and editor β a gift from contributors like you. \
+ "Open CAD Studio is an open-source CAD viewer and editor β a gift from contributors like you. \
Open a DWG/DXF file, start a new drawing, or help shape what comes next.",
)
.size(13)
@@ -1728,9 +1728,9 @@ pub(super) fn start_page_view<'a>() -> Element<'a, Message> {
let cards = row![
card_section(
"Free and open source",
- "H7CAD belongs to its users.",
+ "Open CAD Studio belongs to its users.",
"Source is openly developed and distributed under a permissive licence. \
- You are free to use, study, modify, and share H7CAD.",
+ You are free to use, study, modify, and share Open CAD Studio.",
),
card_section(
"Community driven",
diff --git a/src/io/obj.rs b/src/io/obj.rs
index fd92972c..0f56b223 100644
--- a/src/io/obj.rs
+++ b/src/io/obj.rs
@@ -27,7 +27,7 @@ pub fn parse_obj(src: &str, color: [f32; 4]) -> Option {
"v" => {
let vals: Vec = parts.filter_map(|s| s.parse().ok()).collect();
if vals.len() >= 3 {
- // OBJ: Y-up right-handed. H7CAD viewport is also Y-up β keep as-is.
+ // OBJ: Y-up right-handed. OpenCADStudio viewport is also Y-up β keep as-is.
positions.push([vals[0], vals[1], vals[2]]);
}
}
diff --git a/src/io/pdf_export.rs b/src/io/pdf_export.rs
index 943ea794..823ad80c 100644
--- a/src/io/pdf_export.rs
+++ b/src/io/pdf_export.rs
@@ -78,7 +78,7 @@ fn build_pdf(
rotation_deg: i32,
plot_style: Option<&PlotStyleTable>,
) -> Vec {
- let mut doc = PdfDocument::new("H7CAD Export");
+ let mut doc = PdfDocument::new("Open CAD Studio Export");
let mut ops: Vec = Vec::new();
// White page background.
diff --git a/src/io/print_to_printer.rs b/src/io/print_to_printer.rs
index 14276f4d..5d0b4026 100644
--- a/src/io/print_to_printer.rs
+++ b/src/io/print_to_printer.rs
@@ -28,7 +28,7 @@ pub async fn print_wires(
plot_style: Option,
) -> Result {
// ββ 1. Write to a named temp file βββββββββββββββββββββββββββββββββββββ
- let tmp_path = std::env::temp_dir().join("h7cad_print.pdf");
+ let tmp_path = std::env::temp_dir().join("open_cad_studio_print.pdf");
pdf_export::export_pdf(
&wires,
&hatches,
diff --git a/src/io/step.rs b/src/io/step.rs
index 12abbd67..fbf73c39 100644
--- a/src/io/step.rs
+++ b/src/io/step.rs
@@ -199,7 +199,7 @@ pub fn build_step(meshes: &[&MeshModel]) -> Option {
let msb_id = alloc();
writeln!(
data,
- "#{} = MANIFOLD_SOLID_BREP('H7CAD_Solid',#{});",
+ "#{} = MANIFOLD_SOLID_BREP('OpenCADStudio_Solid',#{});",
msb_id, shell_id
)
.ok();
@@ -217,7 +217,7 @@ pub fn build_step(meshes: &[&MeshModel]) -> Option {
writeln!(data, "#{} = GEOMETRIC_REPRESENTATION_CONTEXT(3);", gc_id).ok();
writeln!(
data,
- "#{sr_id} = SHAPE_REPRESENTATION('H7CAD_Shape',(#{}),#{gc_id});",
+ "#{sr_id} = SHAPE_REPRESENTATION('OpenCADStudio_Shape',(#{}),#{gc_id});",
msb_id
)
.ok();
@@ -227,7 +227,7 @@ pub fn build_step(meshes: &[&MeshModel]) -> Option {
let file = format!(
"ISO-10303-21;\n\
HEADER;\n\
- FILE_DESCRIPTION(('H7CAD STEP export'),'2;1');\n\
+ FILE_DESCRIPTION(('Open CAD Studio STEP export'),'2;1');\n\
FILE_NAME('{ts}','','',(''),'',' ',' ');\n\
FILE_SCHEMA(('CONFIG_CONTROL_DESIGN'));\n\
ENDSEC;\n\
diff --git a/src/io/stl.rs b/src/io/stl.rs
index e45d4135..c34b10e0 100644
--- a/src/io/stl.rs
+++ b/src/io/stl.rs
@@ -67,7 +67,7 @@ pub fn build_stl(meshes: &[&MeshModel]) -> Option> {
// 80-byte header.
let mut header = [0u8; 80];
- let title = b"H7CAD STL export";
+ let title = b"Open CAD Studio STL export";
header[..title.len()].copy_from_slice(title);
buf.extend_from_slice(&header);
diff --git a/src/linetypes.rs b/src/linetypes.rs
index 356720ac..e7b0286a 100644
--- a/src/linetypes.rs
+++ b/src/linetypes.rs
@@ -1,4 +1,4 @@
-//! H7CAD linetype catalog β loaded from `assets/linetypes/H7CAD.lin`.
+//! OpenCADStudio linetype catalog β loaded from `assets/linetypes/OpenCADStudio.lin`.
//!
//! Call [`populate_document`] to add all standard linetypes to a new document.
//! Linetypes that already exist in the document are skipped.
@@ -68,7 +68,7 @@ pub fn complex_lt(name: &str) -> Option<&'static ComplexLt> {
.get(&name.to_ascii_uppercase())
}
-const LIN_SOURCE: &str = include_str!("../assets/linetypes/H7CAD.lin");
+const LIN_SOURCE: &str = include_str!("../assets/linetypes/OpenCADStudio.lin");
// ββ Pattern art extraction ββββββββββββββββββββββββββββββββββββββββββββββββ
@@ -93,7 +93,7 @@ pub fn extract_pattern(desc: &str) -> String {
// ββ Public API ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-/// Add all standard H7CAD linetypes to `doc`, skipping existing ones.
+/// Add all standard OpenCADStudio linetypes to `doc`, skipping existing ones.
pub fn populate_document(doc: &mut CadDocument) {
for mut lt in parse(LIN_SOURCE) {
if !doc.line_types.contains(<.name) {
diff --git a/src/modules/home/draw/arc.rs b/src/modules/home/draw/arc.rs
index 4f6675a2..f9212a70 100644
--- a/src/modules/home/draw/arc.rs
+++ b/src/modules/home/draw/arc.rs
@@ -1,4 +1,4 @@
-// Arc tool β ribbon dropdown + all H7CAD arc creation methods.
+// Arc tool β ribbon dropdown + all OpenCADStudio arc creation methods.
//
// Methods:
// ARC β Center, Start, End (CSE β default)
diff --git a/src/modules/home/draw/circle.rs b/src/modules/home/draw/circle.rs
index fabdcc6a..efc7b54e 100644
--- a/src/modules/home/draw/circle.rs
+++ b/src/modules/home/draw/circle.rs
@@ -1,4 +1,4 @@
-// Circle tool β ribbon dropdown + all H7CAD circle creation methods.
+// Circle tool β ribbon dropdown + all OpenCADStudio circle creation methods.
//
// Methods:
// CIRCLE β Center, Radius (default)
diff --git a/src/modules/home/draw/ellipse.rs b/src/modules/home/draw/ellipse.rs
index 8593ac87..9b9648e1 100644
--- a/src/modules/home/draw/ellipse.rs
+++ b/src/modules/home/draw/ellipse.rs
@@ -1,4 +1,4 @@
-// Ellipse tool β ribbon dropdown + all H7CAD ellipse creation methods.
+// Ellipse tool β ribbon dropdown + all OpenCADStudio ellipse creation methods.
//
// Commands:
// ELLIPSE β Center, Axes (center β major endpoint β minor distance)
diff --git a/src/modules/home/draw/hatch.rs b/src/modules/home/draw/hatch.rs
index 8dced9ed..2936e210 100644
--- a/src/modules/home/draw/hatch.rs
+++ b/src/modules/home/draw/hatch.rs
@@ -1,11 +1,11 @@
-// Hatch/Gradient/Boundary commands β H7CAD Home > Draw > Hatch dropdown.
+// Hatch/Gradient/Boundary commands β OpenCADStudio Home > Draw > Hatch dropdown.
//
// Commands:
// HATCH β ANSI31: 45Β° hatch lines (pick inside or type S for manual)
// GRADIENT β Linear gradient fill (pick inside or type S for manual)
// BOUNDARY β Traces the enclosing boundary as a closed LwPolyline
//
-// Primary workflow (matches H7CAD):
+// Primary workflow (matches OpenCADStudio):
// Click a point INSIDE a closed region β boundary auto-detected.
// Type "S" to switch to manual vertex-picking mode (HATCH/GRADIENT only).
diff --git a/src/modules/home/draw/line.rs b/src/modules/home/draw/line.rs
index 922076db..dfc3e4be 100644
--- a/src/modules/home/draw/line.rs
+++ b/src/modules/home/draw/line.rs
@@ -1,6 +1,6 @@
// Line tool β ribbon definition + interactive command.
//
-// Command: LINE β H7CAD behaviour:
+// Command: LINE β OpenCADStudio behaviour:
// 1. First click β stores start point, prompts for next point
// 2. Each further click β immediately commits an acadrust::Line entity
// (startβend) to the document; end becomes the new start point
diff --git a/src/modules/insert/solid3d_cmds.rs b/src/modules/insert/solid3d_cmds.rs
index 1b72ca75..1ad96ed6 100644
--- a/src/modules/insert/solid3d_cmds.rs
+++ b/src/modules/insert/solid3d_cmds.rs
@@ -9,7 +9,7 @@
// the mesh because the ACIS data is empty. Full ACIS generation requires
// a separate step (out of scope here).
//
-// Coordinate convention in H7CAD: the viewport is Y-up (OpenGL style),
+// Coordinate convention in OpenCADStudio: the viewport is Y-up (OpenGL style),
// so screen XβDXF X, screen ZβDXF Y, screen YβDXF Z (height).
// truck works in standard math coordinates; we map accordingly.
@@ -134,7 +134,7 @@ impl CadCommand for BoxCommand {
}
fn commit_box(p1: Vec3, p2: Vec3, height: f32, color: [f32; 4]) -> CmdResult {
- // Map H7CAD coords to truck: xβx, zβy, yβz
+ // Map OpenCADStudio coords to truck: xβx, zβy, yβz
let x0 = p1.x.min(p2.x) as f64;
let y0 = p1.z.min(p2.z) as f64;
let x1 = p1.x.max(p2.x) as f64;
diff --git a/src/patterns.rs b/src/patterns.rs
index c26b16bc..5ffd20b4 100644
--- a/src/patterns.rs
+++ b/src/patterns.rs
@@ -1,4 +1,4 @@
-//! H7CAD hatch pattern catalog β loaded from `assets/patterns/H7CAD.pat`.
+//! OpenCADStudio hatch pattern catalog β loaded from `assets/patterns/OpenCADStudio.pat`.
//!
//! PAT line format: `angle, x0, y0, dx, dy [, dash1, dash2, ...]`
//! - `angle` line direction in degrees
@@ -8,7 +8,7 @@
use std::sync::OnceLock;
-const PAT_SRC: &str = include_str!("../assets/patterns/H7CAD.pat");
+const PAT_SRC: &str = include_str!("../assets/patterns/OpenCADStudio.pat");
// ββ Public types ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
diff --git a/src/scene/camera.rs b/src/scene/camera.rs
index f36877c7..a0b04fcc 100644
--- a/src/scene/camera.rs
+++ b/src/scene/camera.rs
@@ -9,7 +9,7 @@
// Zoom: adjusts `distance` (exponential feel).
// Snap: directly assigns yaw+pitch encoded as a quaternion (for ViewCube).
//
-// Coordinate convention: Z-up world space (same as the rest of H7CAD).
+// Coordinate convention: Z-up world space (same as the rest of OpenCADStudio).
use glam::{vec3, Mat4, Quat, Vec3};
use iced::{Point, Rectangle};
diff --git a/src/scene/grip.rs b/src/scene/grip.rs
index 5088a765..6be197b8 100644
--- a/src/scene/grip.rs
+++ b/src/scene/grip.rs
@@ -1,4 +1,4 @@
-//! H7CAD-style grip editing.
+//! OpenCADStudio-style grip editing.
use acadrust::Handle;
use glam::{Mat4, Vec3};
@@ -13,7 +13,7 @@ pub const GRIP_HALF_PX: f32 = 5.0;
// ββ Active drag state βββββββββββββββββββββββββββββββββββββββββββββββββββββ
-/// Stored on `H7CAD` while a grip is being dragged.
+/// Stored on `OpenCADStudio` while a grip is being dragged.
#[derive(Clone, Debug)]
pub struct GripEdit {
/// Handle of the entity being edited.
diff --git a/src/scene/hatch_patterns.rs b/src/scene/hatch_patterns.rs
index f9981ac1..d1bb6ef1 100644
--- a/src/scene/hatch_patterns.rs
+++ b/src/scene/hatch_patterns.rs
@@ -1,4 +1,4 @@
-// H7CAD hatch pattern catalog β built from `assets/patterns/H7CAD.pat`.
+// OpenCADStudio hatch pattern catalog β built from `assets/patterns/OpenCADStudio.pat`.
//
// Each `PatternEntry` wraps a parsed PAT pattern with:
// - `gpu` β `HatchPattern::Pattern(families)` for the shader
diff --git a/src/scene/mod.rs b/src/scene/mod.rs
index bfccc54c..3fce3176 100644
--- a/src/scene/mod.rs
+++ b/src/scene/mod.rs
@@ -3914,7 +3914,7 @@ impl Scene {
.document
.views
.iter()
- .find(|v| v.name == "H7CAD_Camera_Model")
+ .find(|v| v.name == "OpenCADStudio_Camera_Model")
.cloned();
if let Some(view) = saved_view {
return self.apply_camera_from_view_entry(&view, true);
@@ -3978,7 +3978,7 @@ impl Scene {
/// Returns true if a valid sheet viewport was found and the camera was set.
fn apply_sheet_viewport_camera(&mut self) -> bool {
// Prefer our named View entry β survives DWG save without being overridden.
- let view_name = format!("H7CAD_Camera_{}", self.current_layout);
+ let view_name = format!("OpenCADStudio_Camera_{}", self.current_layout);
let saved_view = self
.document
.views
@@ -4094,7 +4094,7 @@ impl Scene {
}
// Also write to View table β survives DWG save without override.
- self.write_camera_view_entry("H7CAD_Camera_Model", target_wcs, vd3, view_height);
+ self.write_camera_view_entry("OpenCADStudio_Camera_Model", target_wcs, vd3, view_height);
true
} else {
let target_wcs = acadrust::types::Vector3 {
@@ -4102,7 +4102,7 @@ impl Scene {
y: cam.target.y as f64,
z: cam.target.z as f64,
};
- let view_name = format!("H7CAD_Camera_{}", self.current_layout);
+ let view_name = format!("OpenCADStudio_Camera_{}", self.current_layout);
// Write back to the sheet viewport entity.
let layout_block = self.current_layout_block_handle();
diff --git a/src/scene/pipeline/viewcube.rs b/src/scene/pipeline/viewcube.rs
index fa7a2b35..2ba0685f 100644
--- a/src/scene/pipeline/viewcube.rs
+++ b/src/scene/pipeline/viewcube.rs
@@ -1,4 +1,4 @@
-// ViewCube wgpu pipeline β H7CAD-style interactive 3D navigation cube.
+// ViewCube wgpu pipeline β OpenCADStudio-style interactive 3D navigation cube.
//
// 26 selectable regions: 6 faces + 12 edges + 8 corners.
// Phong shading + hover highlight passed as uniform.
diff --git a/src/snap/mod.rs b/src/snap/mod.rs
index 0a5f611c..724ac6ac 100644
--- a/src/snap/mod.rs
+++ b/src/snap/mod.rs
@@ -1,4 +1,4 @@
-//! H7CAD-style object snap (OSNAP) engine.
+//! OpenCADStudio-style object snap (OSNAP) engine.
//!
//! Implemented modes:
//! Endpoint, Midpoint, Center, Node, Quadrant, Intersection,
@@ -13,7 +13,7 @@ use crate::ui::overlay::CROSSHAIR_ARM;
// ββ Snap type βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-/// Every OSNAP mode β mirrors the H7CAD list.
+/// Every OSNAP mode β mirrors the OpenCADStudio list.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SnapType {
Endpoint,
diff --git a/src/ui/about.rs b/src/ui/about.rs
index f86ce9d6..4e2cd461 100644
--- a/src/ui/about.rs
+++ b/src/ui/about.rs
@@ -57,7 +57,7 @@ pub fn view_window<'a>() -> Element<'a, Message> {
let logo = container(
column![
- text("H7CAD").size(32).color(ACCENT),
+ text("Open CAD Studio").size(32).color(ACCENT),
text("CAD application for Architecture & Engineering")
.size(11)
.color(DIM),
diff --git a/src/ui/app_menu.rs b/src/ui/app_menu.rs
index fa7861ef..9095e99c 100644
--- a/src/ui/app_menu.rs
+++ b/src/ui/app_menu.rs
@@ -1,4 +1,4 @@
-//! Application menu β H7CAD-style dropdown that opens when the H7 logo
+//! Application menu β OpenCADStudio-style dropdown that opens when the OCS logo
//! button is clicked. Overlays the entire viewport as a floating panel.
//!
//! Layout:
@@ -235,7 +235,7 @@ impl AppMenu {
let bottom = container(
row![
iced::widget::Space::new().width(Length::Fill),
- button(text("Exit H7CAD").size(11).color(Color::WHITE))
+ button(text("Exit Open CAD Studio").size(11).color(Color::WHITE))
.on_press(Message::Command("EXIT".into()))
.style(|_: &Theme, status| button::Style {
background: Some(Background::Color(match status {
@@ -299,7 +299,7 @@ impl AppMenu {
// Backdrop β clicking outside closes the menu.
let backdrop = button(
container(panel)
- // Offset so the panel sits just below the ribbon H7 button.
+ // Offset so the panel sits just below the ribbon OCS button.
.padding(iced::Padding {
top: 56.0,
left: 0.0,
@@ -521,7 +521,7 @@ fn recents_file_path() -> Option {
p
};
let mut p = base;
- p.push("H7CAD");
+ p.push("OpenCADStudio");
Some(p.join("recent.txt"))
}
diff --git a/src/ui/command_line.rs b/src/ui/command_line.rs
index 41521bac..32ac0fe8 100644
--- a/src/ui/command_line.rs
+++ b/src/ui/command_line.rs
@@ -1,4 +1,4 @@
-//! H7CAD-style command line β bottom panel with input and history
+//! OpenCADStudio-style command line β bottom panel with input and history
use crate::app::Message;
use iced::widget::{column, container, row, text, text_input};
@@ -41,7 +41,7 @@ pub enum EntryKind {
impl CommandLine {
pub fn new() -> Self {
let mut cl = Self::default();
- cl.push_info("H7CAD ready.");
+ cl.push_info("Open CAD Studio ready.");
cl.push_info("Type a command or use the ribbon. Open OBJ: INSERT tab.");
cl
}
diff --git a/src/ui/properties.rs b/src/ui/properties.rs
index d72c3d3f..71ac2b00 100644
--- a/src/ui/properties.rs
+++ b/src/ui/properties.rs
@@ -1,4 +1,4 @@
-//! Properties panel β H7CAD-style editable object properties.
+//! Properties panel β OpenCADStudio-style editable object properties.
//!
//! Shows two sections (General + Geometry) for the selected entity.
//! β’ Layer β combo_box (options from document layer table)
diff --git a/src/ui/snap_popup.rs b/src/ui/snap_popup.rs
index f9b96d15..a8aef1af 100644
--- a/src/ui/snap_popup.rs
+++ b/src/ui/snap_popup.rs
@@ -1,4 +1,4 @@
-//! H7CAD-style OSNAP dropdown popup panel.
+//! OpenCADStudio-style OSNAP dropdown popup panel.
//!
//! Rendered as a floating overlay above the status bar. The popup is only
//! inserted into the view stack when `snap_popup_open` is true.
diff --git a/src/ui/update_notice.rs b/src/ui/update_notice.rs
index 5fa8c9c7..92b360c0 100644
--- a/src/ui/update_notice.rs
+++ b/src/ui/update_notice.rs
@@ -140,7 +140,7 @@ pub fn view_window<'a>(latest: &'a str, body: &'a str) -> Element<'a, Message> {
let header = container(
column![
text("New Release Available").size(20).color(ACCENT),
- text("A newer H7CAD version is published on GitHub.")
+ text("A newer Open CAD Studio version is published on GitHub.")
.size(11)
.color(DIM),
]
diff --git a/src/update_check.rs b/src/update_check.rs
index 87582ffb..58889c84 100644
--- a/src/update_check.rs
+++ b/src/update_check.rs
@@ -7,9 +7,9 @@
// `None` when up to date / on network failure / on parse error.
const RELEASES_API: &str =
- "https://api.github.com/repos/HakanSeven12/H7CAD/releases/latest";
+ "https://api.github.com/repos/HakanSeven12/open-cad-studio/releases/latest";
pub const RELEASES_PAGE: &str =
- "https://github.com/HakanSeven12/H7CAD/releases/latest";
+ "https://github.com/HakanSeven12/open-cad-studio/releases/latest";
/// What `check_for_update` reports when a newer release exists.
#[derive(Debug, Clone)]
@@ -33,7 +33,7 @@ fn fetch_latest_if_outdated() -> Option {
.timeout(std::time::Duration::from_secs(5))
.build()
.get(RELEASES_API)
- .set("User-Agent", concat!("h7cad/", env!("CARGO_PKG_VERSION")))
+ .set("User-Agent", concat!("OpenCADStudio/", env!("CARGO_PKG_VERSION")))
.set("Accept", "application/vnd.github+json")
.call()
.ok()?