diff --git a/.gitignore b/.gitignore index ea8c4bf..96ef6c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +Cargo.lock diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index f4d0ea2..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,470 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "alga" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f823d037a7ec6ea2197046bafd4ae150e6bc36f9ca347404f46a46823fa84f2" -dependencies = [ - "approx", - "num-complex", - "num-traits", -] - -[[package]] -name = "approx" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3" -dependencies = [ - "num-traits", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "bit-set" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3" - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "byteorder" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" - -[[package]] -name = "capstan" -version = "0.0.3" -dependencies = [ - "alga", - "approx", - "nalgebra", - "num-traits", - "proptest", - "svg", - "thiserror", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "generic-array" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd" -dependencies = [ - "typenum", -] - -[[package]] -name = "getrandom" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa7087f49d294270db4e1928fc110c976cd4b9e5a16348e0a1df09afa99e6c98" - -[[package]] -name = "libm" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" - -[[package]] -name = "matrixmultiply" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4f7ec66360130972f34830bfad9ef05c6610a43938a467bcc9ab9369ab3478f" -dependencies = [ - "rawpointer", -] - -[[package]] -name = "nalgebra" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3f0b89b0a44cb7bb9b62c5e6fd485145ddc6bc14483ab005355e96029b3fbf" -dependencies = [ - "approx", - "generic-array", - "matrixmultiply", - "num-complex", - "num-rational", - "num-traits", - "rand", - "rand_distr", - "simba", - "typenum", -] - -[[package]] -name = "num-complex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "paste" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" -dependencies = [ - "paste-impl", - "proc-macro-hack", -] - -[[package]] -name = "paste-impl" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" -dependencies = [ - "proc-macro-hack", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" - -[[package]] -name = "proc-macro-hack" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598" - -[[package]] -name = "proc-macro2" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "proptest" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12e6c80c1139113c28ee4670dc50cc42915228b51f56a9e407f0ec60f966646f" -dependencies = [ - "bit-set", - "bitflags", - "byteorder", - "lazy_static", - "num-traits", - "quick-error", - "rand", - "rand_chacha", - "rand_xorshift", - "regex-syntax", - "rusty-fork", - "tempfile", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quote" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom", - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_distr" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2" -dependencies = [ - "rand", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rand_xorshift" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rawpointer" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" - -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - -[[package]] -name = "regex-syntax" -version = "0.6.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" - -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - -[[package]] -name = "rusty-fork" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", -] - -[[package]] -name = "simba" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdec3fb717e5504ecbef1cf4223c334a215f95323092afeae57125ec40e4995b" -dependencies = [ - "approx", - "num-complex", - "num-traits", - "paste", -] - -[[package]] -name = "svg" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b65a64d32a41db2a8081aa03c1ccca26f246ff681add693f8b01307b137da79" - -[[package]] -name = "syn" -version = "1.0.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c51d92969d209b54a98397e1b91c8ae82d8c87a7bb87df0b29aa2ad81454228" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "tempfile" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -dependencies = [ - "cfg-if", - "libc", - "rand", - "redox_syscall", - "remove_dir_all", - "winapi", -] - -[[package]] -name = "thiserror" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "typenum" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" - -[[package]] -name = "unicode-xid" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" - -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index acfd41e..42cd989 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,24 +1,29 @@ [package] name = "capstan" -version = "0.0.3" +version = "0.0.4" authors = ["Jonathan Merritt "] -edition = "2018" +edition = "2021" license = "MIT" description = "NURBS library with a CAD focus" homepage = "https://github.com/lancelet/capstan/" repository = "https://github.com/lancelet/capstan/" documentation = "https://docs.rs/capstan" -keywords = ["NURBS", "graphics", "CAD"] -categories = ["algorithms", "graphics", "mathematics"] +keywords = ["NURBS", "graphics", "CAD", "splines", "curves"] +categories = ["algorithms", "graphics", "mathematics", "multimedia"] readme = "README.md" [dependencies] alga = "0.9" -approx = "0.3" -nalgebra = "0.22" +approx = "0.5" +is_sorted = { version = "0.1" } +nalgebra = "0.32" num-traits = "0.2" -svg = "0.8" -thiserror = "1.0" +thiserror-no-std = "2.0" [dev-dependencies] -proptest = "0.10" \ No newline at end of file +proptest = "1.1.0" +svg = "0.13.0" + +[features] +default = [] +unstable = ["is_sorted/unstable"] diff --git a/README.md b/README.md index 6ca4a98..058ec68 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Capstan +# `capstan` ![GitHub Rust CI](https://github.com/lancelet/capstan/workflows/Rust/badge.svg) [![Codecov.io](https://codecov.io/gh/lancelet/capstan/branch/main/graph/badge.svg)](https://codecov.io/gh/lancelet/capstan) @@ -36,4 +36,4 @@ NURBS curve: ## NURBS Curve Representation The library uses the "Rhino" form of NURBS curves, where there are two fewer -knots than in "traditional" NURBS. \ No newline at end of file +knots than in "traditional" NURBS. diff --git a/src/main.rs b/examples/diagrams.rs similarity index 96% rename from src/main.rs rename to examples/diagrams.rs index 14c608f..551b412 100644 --- a/src/main.rs +++ b/examples/diagrams.rs @@ -1,15 +1,14 @@ -extern crate svg; - use nalgebra::Vector2; -use svg::node::element::path; -use svg::node::element::Circle; -use svg::node::element::Group; -use svg::node::element::Path; -use svg::node::Node; -use svg::Document; +use svg::{ + node::{ + element::{path, Circle, Group, Path}, + Node, + }, + Document, +}; -use capstan::knotvec::KnotVec; -type Curve = capstan::curve::Curve>; +use capstan::KnotVec; +type Curve = capstan::Curve>; fn main() { println!("Plotting some examples"); @@ -38,6 +37,7 @@ fn circle_example(filename: &str) { let radius = 130.0; let mut nurbs_circle = unit_circle(); + eprintln!("{:?}", nurbs_circle.de_boor(0.5)); nurbs_circle.uniform_scale(radius); let nurbs_group = curve_and_control_polygon(&nurbs_circle, 256).set("transform", "translate(150, 150)"); diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100755 index 0000000..9d16e37 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,6 @@ +edition = "2021" +unstable_features = true +use_field_init_shorthand = true +reorder_impl_items = true +wrap_comments = true +format_code_in_doc_comments = true diff --git a/src/algebra.rs b/src/algebra.rs index 59af6b6..fef84aa 100644 --- a/src/algebra.rs +++ b/src/algebra.rs @@ -1,8 +1,9 @@ -use nalgebra::base::allocator::Allocator; -use nalgebra::base::{DefaultAllocator, DimName, VectorN}; +use core::{ + fmt::Debug, + ops::{Add, AddAssign, Div, Mul, MulAssign, Sub}, +}; +use nalgebra::base::{allocator::Allocator, DefaultAllocator, DimName, VectorN}; use num_traits::identities::One; -use std::fmt::Debug; -use std::ops::{Add, AddAssign, Div, Mul, MulAssign, Sub}; /// A scalar type. /// diff --git a/src/curve.rs b/src/curve.rs index c1a6bcf..d00af8a 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1,8 +1,8 @@ use crate::algebra::{ScalarT, VectorT}; use crate::knotvec::KnotVec; -use thiserror::Error; +use thiserror_no_std::Error; -pub type Result = std::result::Result; +pub type Result = core::result::Result; /// NURBS curve. /// @@ -42,9 +42,9 @@ where /// * `degree` - polynomial degree of the NURBS curve /// * `control_points` - vector of control points /// * `weights` - vector of weights (must be the same length as - /// `control_points`) + /// `control_points`) /// * `knots` - knot vector (must have `degree + control_points.len() + 1` - /// elements) + /// elements) pub fn new( degree: usize, control_points: Vec, diff --git a/src/knotvec.rs b/src/knotvec.rs index fb7f1fe..483ed82 100644 --- a/src/knotvec.rs +++ b/src/knotvec.rs @@ -1,6 +1,7 @@ +use core::ops::Index; +use is_sorted::IsSorted; + use crate::algebra::ScalarT; -use std::fmt::Debug; -use std::ops::Index; /// Vector of knots in non-decreasing order. /// @@ -30,11 +31,14 @@ impl KnotVec { /// # Example /// /// ``` - /// # use capstan::knotvec::KnotVec; + /// # use capstan::KnotVec; /// let knots = KnotVec::new(vec![0.0, 0.0, 0.0, 1.0, 1.0, 1.0]).unwrap(); /// ``` pub fn new(knots: Vec) -> Option { - if knots.len() >= 2 && knots.is_sorted() && &knots[0] != knots.last().unwrap() { + if knots.len() >= 2 + && IsSorted::is_sorted(&mut knots.iter()) + && &knots[0] != knots.last().unwrap() + { Some(KnotVec { knots }) } else { None @@ -46,7 +50,7 @@ impl KnotVec { /// # Example /// /// ``` - /// # use capstan::knotvec::KnotVec; + /// # use capstan::KnotVec; /// let knots = KnotVec::new(vec![0.0, 0.0, 1.0, 1.0]).unwrap(); /// assert_eq!(knots.len(), 4); /// ``` @@ -145,7 +149,7 @@ impl KnotVec { /// # Examples /// /// ``` - /// # use capstan::knotvec::KnotVec; + /// # use capstan::KnotVec; /// let knots = KnotVec::new(vec![0.0, 0.0, 0.5, 1.0, 1.0]).unwrap(); /// assert_eq!(knots.find_span(0.0), 1); /// assert_eq!(knots.find_span(0.6), 2); diff --git a/src/lib.rs b/src/lib.rs index d2a7850..e291967 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,44 @@ -#![feature(is_sorted)] +//! # NURBS Curve Evaluation +//! +//! The evaluation uses a naive version of the de Boor algorithm. +//! +//! With this it’s possible to evaluate the 3D coordinates of a NURBS curve at +//! any parameter value. +//! +//! ## Example +//! +//! ``` +//! # use nalgebra::Vector2; +//! # use capstan::KnotVec; +//! # type Curve = capstan::Curve>; +//! let r = f32::sqrt(2.0) / 2.0; +//! let degree = 2; +//! let control_points = vec![ +//! Vector2::new(1.0, 0.0), +//! Vector2::new(1.0, 1.0), +//! Vector2::new(0.0, 1.0), +//! Vector2::new(-1.0, 1.0), +//! Vector2::new(-1.0, 0.0), +//! Vector2::new(-1.0, -1.0), +//! Vector2::new(0.0, -1.0), +//! Vector2::new(1.0, -1.0), +//! Vector2::new(1.0, 0.0), +//! ]; +//! let weights = vec![1.0, r, 1.0, r, 1.0, r, 1.0, r, 1.0]; +//! let knots = KnotVec::new(vec![ +//! 0.0, 0.0, 0.0, 0.25, 0.25, 0.5, 0.5, 0.75, 0.75, 1.0, 1.0, 1.0, +//! ]) +//! .unwrap(); +//! +//! let circle = Curve::new(degree, control_points, weights, knots).unwrap(); +//! assert!(-1.0 == circle.de_boor(0.5)[0]); +//! ``` -pub mod algebra; -pub mod curve; -pub mod knotvec; +mod algebra; +pub use algebra::*; + +mod curve; +pub use curve::*; + +mod knotvec; +pub use knotvec::*;