forked from StudioInfinity/dyna3
Compare commits
15 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
de4c2ef482 | ||
![]() |
a309870968 | ||
![]() |
5b331dbbee | ||
![]() |
def40714a7 | ||
![]() |
1054f4e85b | ||
![]() |
cc2da3406b | ||
![]() |
b74cbf10c1 | ||
![]() |
bc17d71f4a | ||
![]() |
a203f6bc1b | ||
![]() |
3664ea73b1 | ||
![]() |
9e74d4e837 | ||
![]() |
0de32f5e11 | ||
![]() |
48a640605a | ||
![]() |
8bedb0baf7 | ||
![]() |
8a0d81d707 |
15 changed files with 3157 additions and 200 deletions
64
README.md
64
README.md
|
@ -12,11 +12,11 @@ Note that currently this is just the barest beginnings of the project, more of a
|
|||
|
||||
### Implementation goals
|
||||
|
||||
* Provide a comfortable, intuitive UI
|
||||
* Comfortable, intuitive UI
|
||||
|
||||
* Allow execution in browser (so implemented in WASM-compatible language)
|
||||
* Able to run in browser (so implemented in WASM-compatible language)
|
||||
|
||||
* Produce scalable graphics of 3D diagrams, and maybe STL files (or other fabricatable file format) as well
|
||||
* Produce scalable graphics of 3D diagrams, and maybe STL files (or other fabricatable file format) as well.
|
||||
|
||||
## Prototype
|
||||
|
||||
|
@ -24,40 +24,38 @@ The latest prototype is in the folder `app-proto`. It includes both a user inter
|
|||
|
||||
### Install the prerequisites
|
||||
|
||||
1. Install [`rustup`](https://rust-lang.github.io/rustup/): the officially recommended Rust toolchain manager.
|
||||
- It's available on Ubuntu as a [Snap](https://snapcraft.io/rustup).
|
||||
2. Call `rustup default stable` to "download the latest stable release of Rust and set it as your default toolchain".
|
||||
- If you forget, the `rustup` [help system](https://github.com/rust-lang/rustup/blob/d9b3601c3feb2e88cf3f8ca4f7ab4fdad71441fd/src/errors.rs#L109-L112) will remind you.
|
||||
3. Call `rustup target add wasm32-unknown-unknown` to add the [most generic 32-bit WebAssembly target](https://doc.rust-lang.org/nightly/rustc/platform-support/wasm32-unknown-unknown.html).
|
||||
4. Call `cargo install wasm-pack` to install the [WebAssembly toolchain](https://rustwasm.github.io/docs/wasm-pack/).
|
||||
5. Call `cargo install trunk` to install the [Trunk](https://trunkrs.dev/) web-build tool.
|
||||
- In the future, `trunk` can be updated with the same command. (You may need the `--locked` flag if your ambient version of `rustc` does not match that required by `trunk`.)
|
||||
1. Install [`rustup`](https://rust-lang.github.io/rustup/): the officially recommended Rust toolchain manager
|
||||
- It's available on Ubuntu as a [Snap](https://snapcraft.io/rustup)
|
||||
2. Call `rustup default stable` to "download the latest stable release of Rust and set it as your default toolchain"
|
||||
- If you forget, the `rustup` [help system](https://github.com/rust-lang/rustup/blob/d9b3601c3feb2e88cf3f8ca4f7ab4fdad71441fd/src/errors.rs#L109-L112) will remind you
|
||||
3. Call `rustup target add wasm32-unknown-unknown` to add the [most generic 32-bit WebAssembly target](https://doc.rust-lang.org/nightly/rustc/platform-support/wasm32-unknown-unknown.html)
|
||||
4. Call `cargo install wasm-pack` to install the [WebAssembly toolchain](https://rustwasm.github.io/docs/wasm-pack/)
|
||||
5. Call `cargo install trunk` to install the [Trunk](https://trunkrs.dev/) web-build tool
|
||||
6. Add the `.cargo/bin` folder in your home directory to your executable search path
|
||||
- This lets you call Trunk, and other tools installed by Cargo, without specifying their paths.
|
||||
- On POSIX systems, the search path is stored in the `PATH` environment variable.
|
||||
- Alternatively, if you don't want to adjust your `PATH`, you can install `trunk` in another directory `DIR` via `cargo install --root DIR trunk`.
|
||||
- This lets you call Trunk, and other tools installed by Cargo, without specifying their paths
|
||||
- On POSIX systems, the search path is stored in the `PATH` environment variable
|
||||
|
||||
### Play with the prototype
|
||||
|
||||
1. From the `app-proto` folder, call `trunk serve --release` to build and serve the prototype.
|
||||
- The crates the prototype depends on will be downloaded and served automatically.
|
||||
- For a faster build, at the expense of a much slower prototype, you can call `trunk serve` without the `--release` flag.
|
||||
1. From the `app-proto` folder, call `trunk serve --release` to build and serve the prototype
|
||||
- The crates the prototype depends on will be downloaded and served automatically
|
||||
- For a faster build, at the expense of a much slower prototype, you can call `trunk serve` without the `--release` flag
|
||||
- If you want to stay in the top-level folder, you can call `trunk serve --config app-proto [--release]` from there instead.
|
||||
3. In a web browser, visit one of the URLs listed under the message `INFO 📡 server listening at:`.
|
||||
- Touching any file in the `app-proto` folder will make Trunk rebuild and live-reload the prototype.
|
||||
4. Press *ctrl+C* in the shell where Trunk is running to stop serving the prototype.
|
||||
3. In a web browser, visit one of the URLs listed under the message `INFO 📡 server listening at:`
|
||||
- Touching any file in the `app-proto` folder will make Trunk rebuild and live-reload the prototype
|
||||
4. Press *ctrl+C* in the shell where Trunk is running to stop serving the prototype
|
||||
|
||||
### Run the engine on some example problems
|
||||
|
||||
1. Use `sh` to run the script `tools/run-examples.sh`.
|
||||
- The script is location-independent, so you can do this from anywhere in the dyna3 repository.
|
||||
1. Use `sh` to run the script `tools/run-examples.sh`
|
||||
- The script is location-independent, so you can do this from anywhere in the dyna3 repository
|
||||
- The call from the top level of the repository is:
|
||||
|
||||
```bash
|
||||
sh tools/run-examples.sh
|
||||
```
|
||||
- For each example problem, the engine will print the value of the loss function at each optimization step.
|
||||
- The first example that prints is the same as the Irisawa hexlet example from the Julia version of the engine prototype. If you go into `engine-proto/gram-test`, launch Julia, and then execute
|
||||
- For each example problem, the engine will print the value of the loss function at each optimization step
|
||||
- The first example that prints is the same as the Irisawa hexlet example from the Julia version of the engine prototype. If you go into `engine-proto/gram-test`, launch Julia, and then
|
||||
|
||||
```julia
|
||||
include("irisawa-hexlet.jl")
|
||||
|
@ -66,24 +64,24 @@ The latest prototype is in the folder `app-proto`. It includes both a user inter
|
|||
end
|
||||
```
|
||||
|
||||
you should see that it prints basically the same loss history until the last few steps, when the lower default precision of the Rust engine really starts to show.
|
||||
you should see that it prints basically the same loss history until the last few steps, when the lower default precision of the Rust engine really starts to show
|
||||
|
||||
### Run the automated tests
|
||||
|
||||
1. Go into the `app-proto` folder.
|
||||
2. Call `cargo test`.
|
||||
1. Go into the `app-proto` folder
|
||||
2. Call `cargo test`
|
||||
|
||||
### Deploy the prototype
|
||||
|
||||
1. From the `app-proto` folder, call `trunk build --release`.
|
||||
- Building in [release mode](https://doc.rust-lang.org/cargo/reference/profiles.html#release) produces an executable which is smaller and often much faster, but harder to debug and more time-consuming to build.
|
||||
- If you want to stay in the top-level folder, you can call `trunk build --config app-proto --release` from there instead.
|
||||
1. From the `app-proto` folder, call `trunk build --release`
|
||||
- Building in [release mode](https://doc.rust-lang.org/cargo/reference/profiles.html#release) produces an executable which is smaller and often much faster, but harder to debug and more time-consuming to build
|
||||
- If you want to stay in the top-level folder, you can call `trunk build --config app-proto --release` from there instead
|
||||
2. Use `sh` to run the packaging script `tools/package-for-deployment.sh`.
|
||||
- The script is location-independent, so you can do this from anywhere in the dyna3 repository.
|
||||
- The script is location-independent, so you can do this from anywhere in the dyna3 repository
|
||||
- The call from the top level of the repository is:
|
||||
```bash
|
||||
sh tools/package-for-deployment.sh
|
||||
```
|
||||
- This will overwrite or replace the files in `deploy/dyna3`.
|
||||
- This will overwrite or replace the files in `deploy/dyna3`
|
||||
3. Put the contents of `deploy/dyna3` in the folder on your server that the prototype will be served from.
|
||||
- To simplify uploading, you might want to combine these files into an archive called `deploy/dyna3.zip`. Git has been set to ignore this path.
|
||||
- To simplify uploading, you might want to combine these files into an archive called `deploy/dyna3.zip`. Git has been set to ignore this path
|
21
app-proto/Cargo.lock
generated
21
app-proto/Cargo.lock
generated
|
@ -255,7 +255,6 @@ dependencies = [
|
|||
"charming",
|
||||
"console_error_panic_hook",
|
||||
"dyna3",
|
||||
"enum-iterator",
|
||||
"itertools",
|
||||
"js-sys",
|
||||
"lazy_static",
|
||||
|
@ -272,26 +271,6 @@ version = "1.13.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "enum-iterator"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4549325971814bda7a44061bf3fe7e487d447cba01e4220a4b454d630d7a016"
|
||||
dependencies = [
|
||||
"enum-iterator-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum-iterator-derive"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "685adfa4d6f3d765a26bc5dbc936577de9abf756c1feeb3089b01dd395034842"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
|
|
|
@ -10,7 +10,6 @@ default = ["console_error_panic_hook"]
|
|||
dev = []
|
||||
|
||||
[dependencies]
|
||||
enum-iterator = "2.3.0"
|
||||
itertools = "0.13.0"
|
||||
js-sys = "0.3.70"
|
||||
lazy_static = "1.5.0"
|
||||
|
|
|
@ -227,6 +227,16 @@ details[open]:has(li) .element-switch::after {
|
|||
border-radius: 8px;
|
||||
}
|
||||
|
||||
#distortion-bar {
|
||||
display: flex;
|
||||
margin-top: 8px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
#distortion-gauge {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
/* display */
|
||||
|
||||
#display {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use enum_iterator::{all, Sequence};
|
||||
use nalgebra::{DMatrix, DVector, DVectorView};
|
||||
use std::{
|
||||
cell::Cell,
|
||||
cmp::Ordering,
|
||||
collections::{BTreeMap, BTreeSet},
|
||||
f64::consts::SQRT_2,
|
||||
fmt,
|
||||
fmt::{Debug, Display, Formatter},
|
||||
fmt::{Debug, Formatter},
|
||||
hash::{Hash, Hasher},
|
||||
rc::Rc,
|
||||
sync::{atomic, atomic::AtomicU64},
|
||||
|
@ -27,7 +27,6 @@ use crate::{
|
|||
ConfigSubspace,
|
||||
ConstraintProblem,
|
||||
DescentHistory,
|
||||
MatrixEntry,
|
||||
Realization,
|
||||
},
|
||||
specified::SpecifiedValue,
|
||||
|
@ -86,14 +85,6 @@ impl Ord for dyn Serial {
|
|||
}
|
||||
}
|
||||
|
||||
// Small helper function to generate consistent errors when there
|
||||
// are indexing issues in a ProblemPoser
|
||||
fn indexing_error(item: &str, name: &str, actor: &str) -> String {
|
||||
format!(
|
||||
"{item} \"{name}\" must be indexed before {actor} writes problem data"
|
||||
)
|
||||
}
|
||||
|
||||
pub trait ProblemPoser {
|
||||
fn pose(&self, problem: &mut ConstraintProblem);
|
||||
}
|
||||
|
@ -132,11 +123,16 @@ pub trait Element: Serial + ProblemPoser + DisplayItem {
|
|||
// be used carefully to preserve invariant (1), described in the comment on
|
||||
// the `tangent` field of the `Assembly` structure
|
||||
fn set_column_index(&self, index: usize);
|
||||
|
||||
/* KLUDGE */
|
||||
fn is_point(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for dyn Element {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
Debug::fmt(&self.id(), f)
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
self.id().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,7 +255,8 @@ impl Serial for Sphere {
|
|||
impl ProblemPoser for Sphere {
|
||||
fn pose(&self, problem: &mut ConstraintProblem) {
|
||||
let index = self.column_index().expect(
|
||||
indexing_error("Sphere", &self.id, "it").as_str());
|
||||
format!("Sphere \"{}\" should be indexed before writing problem data", self.id).as_str()
|
||||
);
|
||||
problem.gram.push_sym(index, index, 1.0);
|
||||
problem.guess.set_column(index, &self.representation.get_clone_untracked());
|
||||
}
|
||||
|
@ -278,7 +275,6 @@ pub struct Point {
|
|||
|
||||
impl Point {
|
||||
const WEIGHT_COMPONENT: usize = 3;
|
||||
const NORM_COMPONENT: usize = 4;
|
||||
|
||||
pub fn new(
|
||||
id: String,
|
||||
|
@ -312,15 +308,6 @@ impl Element for Point {
|
|||
point(0.0, 0.0, 0.0),
|
||||
)
|
||||
}
|
||||
|
||||
fn default_regulators(self: Rc<Self>) -> Vec<Rc<dyn Regulator>> {
|
||||
all::<Axis>()
|
||||
.map(|axis| {
|
||||
Rc::new(PointCoordinateRegulator::new(self.clone(), axis))
|
||||
as Rc::<dyn Regulator>
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn id(&self) -> &String {
|
||||
&self.id
|
||||
|
@ -353,6 +340,10 @@ impl Element for Point {
|
|||
fn set_column_index(&self, index: usize) {
|
||||
self.column_index.set(Some(index));
|
||||
}
|
||||
|
||||
fn is_point(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Serial for Point {
|
||||
|
@ -364,7 +355,8 @@ impl Serial for Point {
|
|||
impl ProblemPoser for Point {
|
||||
fn pose(&self, problem: &mut ConstraintProblem) {
|
||||
let index = self.column_index().expect(
|
||||
indexing_error("Point", &self.id, "it").as_str());
|
||||
format!("Point \"{}\" should be indexed before writing problem data", self.id).as_str()
|
||||
);
|
||||
problem.gram.push_sym(index, index, 0.0);
|
||||
problem.frozen.push(Self::WEIGHT_COMPONENT, index, 0.5);
|
||||
problem.guess.set_column(index, &self.representation.get_clone_untracked());
|
||||
|
@ -375,6 +367,12 @@ pub trait Regulator: Serial + ProblemPoser + OutlineItem {
|
|||
fn subjects(&self) -> Vec<Rc<dyn Element>>;
|
||||
fn measurement(&self) -> ReadSignal<f64>;
|
||||
fn set_point(&self) -> Signal<SpecifiedValue>;
|
||||
fn soft(&self) -> Option<Signal<bool>> {
|
||||
None
|
||||
}
|
||||
fn distortion(&self) -> Option<ReadSignal<f64>> { /* KLUDGE */
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for dyn Regulator {
|
||||
|
@ -407,6 +405,8 @@ pub struct InversiveDistanceRegulator {
|
|||
pub subjects: [Rc<dyn Element>; 2],
|
||||
pub measurement: ReadSignal<f64>,
|
||||
pub set_point: Signal<SpecifiedValue>,
|
||||
pub soft: Signal<bool>,
|
||||
distortion: Option<ReadSignal<f64>>, /* KLUDGE */
|
||||
serial: u64,
|
||||
}
|
||||
|
||||
|
@ -422,9 +422,24 @@ impl InversiveDistanceRegulator {
|
|||
});
|
||||
|
||||
let set_point = create_signal(SpecifiedValue::from_empty_spec());
|
||||
let distortion = if subjects.iter().all(|subj| subj.is_point()) {
|
||||
Some(create_memo(move || {
|
||||
let set_point_opt = set_point.with(|set_pt| set_pt.value);
|
||||
let measurement_val = measurement.get();
|
||||
match set_point_opt {
|
||||
None => 0.0,
|
||||
Some(set_point_val) => SQRT_2 * (
|
||||
(-measurement_val).sqrt() - (-set_point_val).sqrt()
|
||||
),
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let soft = create_signal(false);
|
||||
let serial = Self::next_serial();
|
||||
|
||||
Self { subjects, measurement, set_point, serial }
|
||||
Self { subjects, measurement, set_point, soft, distortion, serial }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -440,6 +455,14 @@ impl Regulator for InversiveDistanceRegulator {
|
|||
fn set_point(&self) -> Signal<SpecifiedValue> {
|
||||
self.set_point
|
||||
}
|
||||
|
||||
fn soft(&self) -> Option<Signal<bool>> {
|
||||
Some(self.soft)
|
||||
}
|
||||
|
||||
fn distortion(&self) -> Option<ReadSignal<f64>> {
|
||||
self.distortion
|
||||
}
|
||||
}
|
||||
|
||||
impl Serial for InversiveDistanceRegulator {
|
||||
|
@ -450,28 +473,33 @@ impl Serial for InversiveDistanceRegulator {
|
|||
|
||||
impl ProblemPoser for InversiveDistanceRegulator {
|
||||
fn pose(&self, problem: &mut ConstraintProblem) {
|
||||
let soft = self.soft.get_untracked();
|
||||
self.set_point.with_untracked(|set_pt| {
|
||||
if let Some(val) = set_pt.value {
|
||||
let [row, col] = self.subjects.each_ref().map(
|
||||
|subj| subj.column_index().expect(
|
||||
indexing_error("Subject", subj.id(),
|
||||
"inversive distance regulator").as_str())
|
||||
"Subjects should be indexed before inversive distance regulator writes problem data"
|
||||
)
|
||||
);
|
||||
problem.gram.push_sym(row, col, val);
|
||||
if soft {
|
||||
problem.soft.push_sym(row, col, val);
|
||||
} else {
|
||||
problem.gram.push_sym(row, col, val);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HalfCurvatureRegulator {
|
||||
pub subject: Rc<Sphere>,
|
||||
pub subject: Rc<dyn Element>,
|
||||
pub measurement: ReadSignal<f64>,
|
||||
pub set_point: Signal<SpecifiedValue>,
|
||||
serial: u64,
|
||||
}
|
||||
|
||||
impl HalfCurvatureRegulator {
|
||||
pub fn new(subject: Rc<Sphere>) -> Self {
|
||||
pub fn new(subject: Rc<dyn Element>) -> Self {
|
||||
let measurement = subject.representation().map(
|
||||
|rep| rep[Sphere::CURVATURE_COMPONENT]
|
||||
);
|
||||
|
@ -508,85 +536,14 @@ impl ProblemPoser for HalfCurvatureRegulator {
|
|||
self.set_point.with_untracked(|set_pt| {
|
||||
if let Some(val) = set_pt.value {
|
||||
let col = self.subject.column_index().expect(
|
||||
indexing_error("Subject", &self.subject.id,
|
||||
"half-curvature regulator").as_str());
|
||||
"Subject should be indexed before half-curvature regulator writes problem data"
|
||||
);
|
||||
problem.frozen.push(Sphere::CURVATURE_COMPONENT, col, val);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Sequence)]
|
||||
pub enum Axis { X = 0, Y = 1, Z = 2 }
|
||||
|
||||
impl Axis {
|
||||
fn name(&self) -> &'static str {
|
||||
match self { Axis::X => "X", Axis::Y => "Y", Axis::Z => "Z" }
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Axis {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(self.name())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PointCoordinateRegulator {
|
||||
pub subject: Rc<Point>,
|
||||
pub axis: Axis,
|
||||
pub measurement: ReadSignal<f64>,
|
||||
pub set_point: Signal<SpecifiedValue>,
|
||||
serial: u64
|
||||
}
|
||||
|
||||
impl PointCoordinateRegulator {
|
||||
pub fn new(subject: Rc<Point>, axis: Axis) -> Self {
|
||||
let measurement = subject.representation().map(
|
||||
move |rep| rep[axis as usize]
|
||||
);
|
||||
let set_point = create_signal(SpecifiedValue::from_empty_spec());
|
||||
Self { subject, axis, measurement, set_point, serial: Self::next_serial() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Serial for PointCoordinateRegulator {
|
||||
fn serial(&self) -> u64 { self.serial }
|
||||
}
|
||||
|
||||
impl Regulator for PointCoordinateRegulator {
|
||||
fn subjects(&self) -> Vec<Rc<dyn Element>> { vec![self.subject.clone()] }
|
||||
fn measurement(&self) -> ReadSignal<f64> { self.measurement }
|
||||
fn set_point(&self) -> Signal<SpecifiedValue> { self.set_point }
|
||||
}
|
||||
|
||||
impl ProblemPoser for PointCoordinateRegulator {
|
||||
fn pose(&self, problem: &mut ConstraintProblem) {
|
||||
self.set_point.with_untracked(|set_pt| {
|
||||
if let Some(val) = set_pt.value {
|
||||
let col = self.subject.column_index().expect(
|
||||
indexing_error("Subject", &self.subject.id,
|
||||
"point-coordinate regulator").as_str());
|
||||
problem.frozen.push(self.axis as usize, col, val);
|
||||
// If all three of the subject's spatial coordinates have been
|
||||
// frozen, then freeze its norm component:
|
||||
let mut coords = [0.0; Axis::CARDINALITY];
|
||||
let mut nset: usize = 0;
|
||||
for &MatrixEntry {index, value} in &(problem.frozen) {
|
||||
if index.1 == col && index.0 < Axis::CARDINALITY {
|
||||
nset += 1;
|
||||
coords[index.0] = value
|
||||
}
|
||||
}
|
||||
if nset == Axis::CARDINALITY {
|
||||
let [x, y, z] = coords;
|
||||
problem.frozen.push(
|
||||
Point::NORM_COMPONENT, col, point(x,y,z)[Point::NORM_COMPONENT]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// the velocity is expressed in uniform coordinates
|
||||
pub struct ElementMotion<'a> {
|
||||
pub element: Rc<dyn Element>,
|
||||
|
@ -787,7 +744,6 @@ impl Assembly {
|
|||
/* DEBUG */
|
||||
// log the Gram matrix
|
||||
console_log!("Gram matrix:\n{}", problem.gram);
|
||||
console_log!("Frozen entries:\n{}", problem.frozen);
|
||||
|
||||
/* DEBUG */
|
||||
// log the initial configuration matrix
|
||||
|
@ -795,7 +751,7 @@ impl Assembly {
|
|||
|
||||
// look for a configuration with the given Gram matrix
|
||||
let Realization { result, history } = realize_gram(
|
||||
&problem, 1.0e-12, 0.5, 0.9, 1.1, 200, 110
|
||||
&problem, 1.0e-20, 0.5, 0.9, 1.1, 400, 110
|
||||
);
|
||||
|
||||
/* DEBUG */
|
||||
|
@ -947,8 +903,7 @@ mod tests {
|
|||
use crate::engine;
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected =
|
||||
"Sphere \"sphere\" must be indexed before it writes problem data")]
|
||||
#[should_panic(expected = "Sphere \"sphere\" should be indexed before writing problem data")]
|
||||
fn unindexed_element_test() {
|
||||
let _ = create_root(|| {
|
||||
let elt = Sphere::default("sphere".to_string(), 0);
|
||||
|
@ -957,8 +912,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Subject \"sphere1\" must be indexed before \
|
||||
inversive distance regulator writes problem data")]
|
||||
#[should_panic(expected = "Subjects should be indexed before inversive distance regulator writes problem data")]
|
||||
fn unindexed_subject_test_inversive_distance() {
|
||||
let _ = create_root(|| {
|
||||
let subjects = [0, 1].map(
|
||||
|
@ -1019,4 +973,4 @@ mod tests {
|
|||
assert!((final_half_curv / INITIAL_HALF_CURV - 1.0).abs() < DRIFT_TOL);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -111,6 +111,94 @@ fn StepInput() -> View {
|
|||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn DistortionGauge() -> View {
|
||||
let state = use_context::<AppState>();
|
||||
let total_distortion = create_memo(move || {
|
||||
state.assembly.regulators.with(|regs| {
|
||||
let mut total = 0.0;
|
||||
for reg in regs {
|
||||
if let Some(distortion) = reg.distortion() {
|
||||
total += distortion.get().abs();
|
||||
}
|
||||
}
|
||||
total
|
||||
})
|
||||
});
|
||||
|
||||
view! {
|
||||
div(id = "distortion-gauge") {
|
||||
"Distortion: " (total_distortion.with(|distort| distort.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn PrintButton() -> View {
|
||||
view! {
|
||||
button(
|
||||
on:click = |_| {
|
||||
let state = use_context::<AppState>();
|
||||
|
||||
// print the edge length distortions
|
||||
let mut hard_distortion_table = String::new();
|
||||
let mut soft_distortion_table = String::new();
|
||||
let mut highest_distortion = f64::NEG_INFINITY;
|
||||
let mut lowest_distortion = f64::INFINITY;
|
||||
let mut largest_hard_distortion = f64::NEG_INFINITY;
|
||||
state.assembly.regulators.with_untracked(|regs| {
|
||||
for reg in regs {
|
||||
if let Some(distortion) = reg.distortion() {
|
||||
let distortion_val = distortion.get();
|
||||
let subjects = reg.subjects();
|
||||
let distortion_line = format!(
|
||||
"{}, {}: {distortion_val}\n",
|
||||
subjects[0].id(),
|
||||
subjects[1].id(),
|
||||
);
|
||||
match reg.soft() {
|
||||
Some(soft) if soft.get() => {
|
||||
soft_distortion_table += &distortion_line;
|
||||
highest_distortion = highest_distortion.max(distortion_val);
|
||||
lowest_distortion = lowest_distortion.min(distortion_val);
|
||||
},
|
||||
_ => {
|
||||
hard_distortion_table += &distortion_line;
|
||||
largest_hard_distortion = largest_hard_distortion.max(distortion_val.abs());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
console_log!("\
|
||||
=== Distortions of flexible edges (for labels) ===\n\n\
|
||||
--- Range ---\n\n\
|
||||
Highest: {highest_distortion}\n\
|
||||
Lowest: {lowest_distortion}\n\n\
|
||||
--- Table ---\n\n{soft_distortion_table}\n\
|
||||
=== Distortions of rigid edges (for validation) ===\n\n\
|
||||
These values should be small relative to the ones for the flexible edges\n\n\
|
||||
--- Range ---\n\n\
|
||||
Largest absolute: {largest_hard_distortion}\n\n\
|
||||
--- Table ---\n\n{hard_distortion_table}\
|
||||
");
|
||||
|
||||
// print the vertex coordinates
|
||||
let mut coords_table = String::new();
|
||||
state.assembly.elements.with_untracked(|elts| {
|
||||
for elt in elts.iter().filter(|elt| elt.is_point()) {
|
||||
let (x, y, z) = elt.representation().with(
|
||||
|rep| (rep[0], rep[1], rep[2])
|
||||
);
|
||||
coords_table += &format!("{}: {x}, {y}, {z}\n", elt.id());
|
||||
}
|
||||
});
|
||||
console_log!("=== Vertex coordinates ===\n\n{coords_table}");
|
||||
},
|
||||
) { "Print" }
|
||||
}
|
||||
}
|
||||
|
||||
fn into_log10_time_point((step, value): (usize, f64)) -> Vec<Option<f64>> {
|
||||
vec![
|
||||
Some(step as f64),
|
||||
|
@ -315,6 +403,10 @@ pub fn Diagnostics() -> View {
|
|||
}
|
||||
DiagnosticsPanel(name = "loss") { LossHistory {} }
|
||||
DiagnosticsPanel(name = "spectrum") { SpectrumHistory {} }
|
||||
div(id = "distortion-bar") {
|
||||
DistortionGauge {}
|
||||
PrintButton {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -597,16 +597,16 @@ pub fn Display() -> View {
|
|||
|status| status.is_ok()
|
||||
);
|
||||
let step_val = state.assembly.step.with_untracked(|step| step.value);
|
||||
let on_init_step = step_val.is_some_and(|n| n == 0.0);
|
||||
let on_last_step = step_val.is_some_and(
|
||||
|n| state.assembly.descent_history.with_untracked(
|
||||
|history| n as usize + 1 == history.config.len().max(1)
|
||||
)
|
||||
);
|
||||
let on_manipulable_step =
|
||||
!realization_successful && on_init_step
|
||||
|| realization_successful && on_last_step;
|
||||
if on_manipulable_step && state.selection.with(|sel| sel.len() == 1) {
|
||||
if
|
||||
state.selection.with(|sel| sel.len() == 1)
|
||||
&& realization_successful
|
||||
&& on_last_step
|
||||
{
|
||||
let sel = state.selection.with(
|
||||
|sel| sel.into_iter().next().unwrap().clone()
|
||||
);
|
||||
|
|
|
@ -9,7 +9,6 @@ use crate::{
|
|||
Element,
|
||||
HalfCurvatureRegulator,
|
||||
InversiveDistanceRegulator,
|
||||
PointCoordinateRegulator,
|
||||
Regulator,
|
||||
},
|
||||
specified::SpecifiedValue
|
||||
|
@ -120,20 +119,6 @@ impl OutlineItem for HalfCurvatureRegulator {
|
|||
}
|
||||
}
|
||||
|
||||
impl OutlineItem for PointCoordinateRegulator {
|
||||
fn outline_item(self: Rc<Self>, _element: &Rc<dyn Element>) -> View {
|
||||
let name = format!("{} coordinate", self.axis);
|
||||
view! {
|
||||
li(class = "regulator") {
|
||||
div(class = "regulator-label") // for spacing
|
||||
div(class = "regulator-type") { (name) }
|
||||
RegulatorInput(regulator = self)
|
||||
div(class = "status")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// a list item that shows an element in an outline view of an assembly
|
||||
#[component(inline_props)]
|
||||
fn ElementOutlineItem(element: Rc<dyn Element>) -> View {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,7 @@
|
|||
use lazy_static::lazy_static;
|
||||
use nalgebra::{Const, DMatrix, DVector, DVectorView, Dyn, SymmetricEigen};
|
||||
use std::fmt::{Display, Error, Formatter};
|
||||
use sycamore::prelude::console_log; /* DEBUG */
|
||||
|
||||
// --- elements ---
|
||||
|
||||
|
@ -52,8 +53,8 @@ pub fn project_point_to_normalized(rep: &mut DVector<f64>) {
|
|||
// --- partial matrices ---
|
||||
|
||||
pub struct MatrixEntry {
|
||||
pub index: (usize, usize),
|
||||
pub value: f64,
|
||||
index: (usize, usize),
|
||||
value: f64,
|
||||
}
|
||||
|
||||
pub struct PartialMatrix(Vec<MatrixEntry>);
|
||||
|
@ -240,6 +241,7 @@ impl DescentHistory {
|
|||
|
||||
pub struct ConstraintProblem {
|
||||
pub gram: PartialMatrix,
|
||||
pub soft: PartialMatrix,
|
||||
pub frozen: PartialMatrix,
|
||||
pub guess: DMatrix<f64>,
|
||||
}
|
||||
|
@ -249,6 +251,7 @@ impl ConstraintProblem {
|
|||
const ELEMENT_DIM: usize = 5;
|
||||
Self {
|
||||
gram: PartialMatrix::new(),
|
||||
soft: PartialMatrix::new(),
|
||||
frozen: PartialMatrix::new(),
|
||||
guess: DMatrix::<f64>::zeros(ELEMENT_DIM, element_count),
|
||||
}
|
||||
|
@ -258,6 +261,7 @@ impl ConstraintProblem {
|
|||
pub fn from_guess(guess_columns: &[DVector<f64>]) -> Self {
|
||||
Self {
|
||||
gram: PartialMatrix::new(),
|
||||
soft: PartialMatrix::new(),
|
||||
frozen: PartialMatrix::new(),
|
||||
guess: DMatrix::from_columns(guess_columns),
|
||||
}
|
||||
|
@ -280,14 +284,18 @@ lazy_static! {
|
|||
struct SearchState {
|
||||
config: DMatrix<f64>,
|
||||
err_proj: DMatrix<f64>,
|
||||
loss_hard: f64,
|
||||
loss: f64,
|
||||
}
|
||||
|
||||
impl SearchState {
|
||||
fn from_config(gram: &PartialMatrix, config: DMatrix<f64>) -> Self {
|
||||
let err_proj = gram.sub_proj(&(config.tr_mul(&*Q) * &config));
|
||||
fn from_config(gram: &PartialMatrix, soft: &PartialMatrix, softness: f64, config: DMatrix<f64>) -> Self {
|
||||
let config_gram = &(config.tr_mul(&*Q) * &config);
|
||||
let err_proj_hard = gram.sub_proj(config_gram);
|
||||
let err_proj = &err_proj_hard + softness * soft.sub_proj(config_gram);
|
||||
let loss_hard = err_proj_hard.norm_squared();
|
||||
let loss = err_proj.norm_squared();
|
||||
Self { config, err_proj, loss }
|
||||
Self { config, err_proj, loss_hard, loss }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,6 +339,8 @@ pub fn local_unif_to_std(v: DVectorView<f64>) -> DMatrix<f64> {
|
|||
// use backtracking line search to find a better configuration
|
||||
fn seek_better_config(
|
||||
gram: &PartialMatrix,
|
||||
soft: &PartialMatrix,
|
||||
softness: f64,
|
||||
state: &SearchState,
|
||||
base_step: &DMatrix<f64>,
|
||||
base_target_improvement: f64,
|
||||
|
@ -341,7 +351,7 @@ fn seek_better_config(
|
|||
let mut rate = 1.0;
|
||||
for backoff_steps in 0..max_backoff_steps {
|
||||
let trial_config = &state.config + rate * base_step;
|
||||
let trial_state = SearchState::from_config(gram, trial_config);
|
||||
let trial_state = SearchState::from_config(gram, soft, softness, trial_config);
|
||||
let improvement = state.loss - trial_state.loss;
|
||||
if improvement >= min_efficiency * rate * base_target_improvement {
|
||||
return Some((trial_state, backoff_steps));
|
||||
|
@ -376,7 +386,7 @@ pub fn realize_gram(
|
|||
max_backoff_steps: i32,
|
||||
) -> Realization {
|
||||
// destructure the problem data
|
||||
let ConstraintProblem { gram, guess, frozen } = problem;
|
||||
let ConstraintProblem { gram, soft, guess, frozen } = problem;
|
||||
|
||||
// start the descent history
|
||||
let mut history = DescentHistory::new();
|
||||
|
@ -403,13 +413,18 @@ pub fn realize_gram(
|
|||
let scale_adjustment = (gram.0.len() as f64).sqrt();
|
||||
let tol = scale_adjustment * scaled_tol;
|
||||
|
||||
// set up constants and variables related to minimizing the soft loss
|
||||
const GRAD_TOL: f64 = 1e-12;
|
||||
let mut grad_size = f64::INFINITY;
|
||||
let mut softness = 1.0;
|
||||
|
||||
// convert the frozen indices to stacked format
|
||||
let frozen_stacked: Vec<usize> = frozen.into_iter().map(
|
||||
|MatrixEntry { index: (row, col), .. }| col*element_dim + row
|
||||
).collect();
|
||||
|
||||
// use a regularized Newton's method with backtracking
|
||||
let mut state = SearchState::from_config(gram, frozen.freeze(guess));
|
||||
let mut state = SearchState::from_config(gram, soft, softness, frozen.freeze(guess));
|
||||
let mut hess = DMatrix::zeros(element_dim, assembly_dim);
|
||||
for _ in 0..max_descent_steps {
|
||||
// find the negative gradient of the loss function
|
||||
|
@ -426,7 +441,7 @@ pub fn realize_gram(
|
|||
let neg_d_err =
|
||||
basis_mat.tr_mul(&*Q) * &state.config
|
||||
+ state.config.tr_mul(&*Q) * &basis_mat;
|
||||
let neg_d_err_proj = gram.proj(&neg_d_err);
|
||||
let neg_d_err_proj = gram.proj(&neg_d_err) + softness * soft.proj(&neg_d_err);
|
||||
let deriv_grad = 4.0 * &*Q * (
|
||||
-&basis_mat * &state.err_proj
|
||||
+ &state.config * &neg_d_err_proj
|
||||
|
@ -455,10 +470,13 @@ pub fn realize_gram(
|
|||
hess[(k, k)] = 1.0;
|
||||
}
|
||||
|
||||
// stop if the loss is tolerably low
|
||||
// stop if the hard loss is tolerably low and the total loss is close to
|
||||
// stationary. we use `neg_grad_stacked` to measure the size of the
|
||||
// gradient because it's been projected onto the frozen subspace
|
||||
history.config.push(state.config.clone());
|
||||
history.scaled_loss.push(state.loss / scale_adjustment);
|
||||
if state.loss < tol { break; }
|
||||
history.scaled_loss.push(state.loss_hard / scale_adjustment);
|
||||
grad_size = neg_grad_stacked.norm_squared();
|
||||
if state.loss_hard < tol && grad_size < softness * GRAD_TOL { break; }
|
||||
|
||||
// compute the Newton step
|
||||
/* TO DO */
|
||||
|
@ -482,7 +500,7 @@ pub fn realize_gram(
|
|||
|
||||
// use backtracking line search to find a better configuration
|
||||
if let Some((better_state, backoff_steps)) = seek_better_config(
|
||||
gram, &state, &base_step, neg_grad.dot(&base_step),
|
||||
gram, soft, softness, &state, &base_step, neg_grad.dot(&base_step),
|
||||
min_efficiency, backoff, max_backoff_steps,
|
||||
) {
|
||||
state = better_state;
|
||||
|
@ -493,8 +511,18 @@ pub fn realize_gram(
|
|||
history,
|
||||
};
|
||||
}
|
||||
|
||||
// if we're near a minimum of the total loss, but the hard loss still
|
||||
// isn't tolerably low, make the soft constraints softer
|
||||
const SOFTNESS_BACKOFF_THRESHOLD: f64 = 1e-6;
|
||||
const SOFTNESS_BACKOFF: f64 = 0.95;
|
||||
if state.loss_hard >= tol && grad_size < softness * SOFTNESS_BACKOFF_THRESHOLD {
|
||||
softness *= SOFTNESS_BACKOFF;
|
||||
state = SearchState::from_config(gram, soft, softness, state.config);
|
||||
console_log!("Softness decreased to {softness}");
|
||||
}
|
||||
}
|
||||
let result = if state.loss < tol {
|
||||
let result = if state.loss_hard < tol && grad_size < softness * GRAD_TOL {
|
||||
// express the uniform basis in the standard basis
|
||||
const UNIFORM_DIM: usize = 4;
|
||||
let total_dim_unif = UNIFORM_DIM * assembly_dim;
|
||||
|
|
59
impossolid/angle-distortion.py
Normal file
59
impossolid/angle-distortion.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
import collections
|
||||
import math
|
||||
import sys
|
||||
|
||||
def read_edge_distortions(filename):
|
||||
vertices = set()
|
||||
distortions = {}
|
||||
with open(filename, 'r') as edge_file:
|
||||
while edge_line := edge_file.readline():
|
||||
line_parts = edge_line.rstrip().split(': ')
|
||||
endpoints = tuple(sorted(line_parts[0].split(', ')))
|
||||
vertices.update(endpoints)
|
||||
if len(line_parts) > 1:
|
||||
distortions[endpoints] = float(line_parts[1])
|
||||
else:
|
||||
distortions[endpoints] = 0
|
||||
return (vertices, distortions)
|
||||
|
||||
def find_triangles(vertices, edges):
|
||||
triangles = []
|
||||
for e in sorted(edges):
|
||||
for v in sorted(vertices):
|
||||
if e[1] < v:
|
||||
if (e[0], v) in edges and (e[1], v) in edges:
|
||||
triangles.append((e[0], e[1], v))
|
||||
return triangles
|
||||
|
||||
# use the law of cosines to get the angle distortion
|
||||
def angle_distortion(edge_distortions):
|
||||
a, b, c = list(edge_distortions)
|
||||
cos_angle_a = (1 + 2*(b + c - a) + b*b + c*c - a*a) / (2*(1 + b)*(1 + c))
|
||||
return math.degrees(math.acos(cos_angle_a)) - 60
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) <= 1:
|
||||
print('Pass the path to the file that lists the edge distortions')
|
||||
else:
|
||||
vertices, distortions = read_edge_distortions(sys.argv[1])
|
||||
triangles = find_triangles(vertices, distortions.keys())
|
||||
total_angle_distortion = 0
|
||||
highest_angle_distortion = -math.inf
|
||||
lowest_angle_distortion = math.inf
|
||||
print('{} triangles\n'.format(len(triangles)))
|
||||
for t in triangles:
|
||||
print('Triangle {0}, {1}, {2}'.format(t[0], t[1], t[2]))
|
||||
edge_distortions = collections.deque(
|
||||
[distortions[(t[j], t[k])] for (j, k) in [(1, 2), (0, 1), (0, 2)]]
|
||||
)
|
||||
for k in range(3):
|
||||
ang_distort = angle_distortion(edge_distortions)
|
||||
total_angle_distortion += abs(ang_distort)
|
||||
highest_angle_distortion = max(highest_angle_distortion, ang_distort)
|
||||
lowest_angle_distortion = min(lowest_angle_distortion, ang_distort)
|
||||
print(' {0}: {1}°'.format(t[k], ang_distort))
|
||||
edge_distortions.rotate()
|
||||
print()
|
||||
print('Total angle distortion: {}°'.format(total_angle_distortion))
|
||||
print('Highest angle distortion: {}°'.format(highest_angle_distortion))
|
||||
print('Lowest angle distortion: {}°'.format(lowest_angle_distortion))
|
150
impossolid/twice-augmented
Normal file
150
impossolid/twice-augmented
Normal file
|
@ -0,0 +1,150 @@
|
|||
=== Distortions of flexible edges (for labels) ===
|
||||
|
||||
--- Range ---
|
||||
|
||||
Highest: 0.000039581305103782685
|
||||
Lowest: -0.00003959022952266363
|
||||
|
||||
--- Table ---
|
||||
|
||||
a_SE, b_SE: 0.000015249448583054653
|
||||
b_SW, c_S: 0.000006918255000202575
|
||||
b_SE, c_S: 0.00001022525369434997
|
||||
b_SE, c_E: 0.000010225282824746383
|
||||
b_NE, c_E: 0.000006918450075555058
|
||||
z_S, a_SW: -0.0000219346808875234
|
||||
z_S, a_SE: 0.00002021118621352795
|
||||
z_E, a_SE: 0.00002021122888534378
|
||||
z_E, a_NE: -0.00002193465480671757
|
||||
z_S, b_SW: 0.000015276737515369292
|
||||
z_S, b_SE: -0.000010771908316892743
|
||||
z_E, b_SE: -0.00001077200999765046
|
||||
z_E, b_NE: 0.000015276631362360217
|
||||
z_S, c_S: -0.0000027853351723499016
|
||||
z_E, c_E: -0.000002785228607191555
|
||||
c_N, d_NE: -0.000007632775579087326
|
||||
c_N, d_NW: 0.00001402754980516112
|
||||
c_W, d_NW: 0.000014028001282264439
|
||||
c_W, d_SW: -0.00000763316944431703
|
||||
c_S, d_SW: 0.000006566974972180328
|
||||
c_S, d_SE: -0.0000033161321458747414
|
||||
c_E, d_SE: -0.00000331586236646513
|
||||
c_E, d_NE: 0.000006566624318564243
|
||||
y_NE, b_NE: -0.0000017608392620486498
|
||||
y_NW, b_NW: -0.00003959022952266363
|
||||
y_SW, b_SW: -0.0000017608153313274316
|
||||
y_SE, b_SE: 0.000005637007821097203
|
||||
y_NE, c_N: 0.000001760310254250749
|
||||
y_NW, c_N: 0.00003958128591112948
|
||||
y_NW, c_W: 0.000039581305103782685
|
||||
y_SW, c_W: 0.0000017603065237110672
|
||||
y_SW, c_S: 0.0000017602552603493003
|
||||
y_SE, c_S: -0.00000563497752606038
|
||||
y_SE, c_E: -0.0000056349905677193694
|
||||
y_NE, c_E: 0.0000017602528935919282
|
||||
y_NE, d_NE: -0.0000017608481082635805
|
||||
y_NW, d_NW: -0.0000395891283971962
|
||||
y_SW, d_SW: -0.0000017608381747596222
|
||||
y_SE, d_SE: 0.0000056371661583272735
|
||||
d_NE, e_N: 0.000007303314580670295
|
||||
d_NW, e_N: -0.000016255656816635924
|
||||
d_NW, e_W: -0.000016256069869023512
|
||||
d_SW, e_W: 0.00000730369455466398
|
||||
d_SW, e_S: -0.000006000901856373712
|
||||
d_SE, e_S: 0.000003879307405619109
|
||||
d_SE, e_E: 0.000003879053499059208
|
||||
d_NE, e_E: -0.00000600059436381427
|
||||
c_N, e_N: 0.00000899767908293228
|
||||
c_W, e_W: 0.000008997328779446816
|
||||
c_S, e_S: 0.0000042757526759396545
|
||||
c_E, e_E: 0.000004275945999382972
|
||||
e_N, f_NE: 0.0000026971057195376348
|
||||
e_N, f_NW: 0.000006498321003978716
|
||||
e_W, f_NW: 0.000006498333167484994
|
||||
e_W, f_SW: 0.000002697065747495785
|
||||
e_S, f_SW: 0.000001359196116957704
|
||||
e_S, f_SE: 0.0000010550443264554641
|
||||
e_E, f_SE: 0.0000010550540852081317
|
||||
e_E, f_NE: 0.000001359177866673992
|
||||
d_NE, f_NE: -0.0000029405886467824407
|
||||
d_NW, f_NW: -0.000009421855439304757
|
||||
d_SW, f_SW: -0.000002940615976753832
|
||||
d_SE, f_SE: -0.000001529705558996715
|
||||
f_NE, g_ENE: -0.00000011649787286240574
|
||||
f_NE, g_NNE: -0.000002135681696645076
|
||||
f_NW, g_NNW: -0.000003607774033318148
|
||||
f_NW, g_WNW: -0.000003607785721714447
|
||||
f_SW, g_WSW: -0.0000021356459140809334
|
||||
f_SW, g_SSW: -0.00000011652747271646458
|
||||
f_SE, g_SSE: -0.0000005858121892925972
|
||||
f_SE, g_ESE: -0.0000005858113552594831
|
||||
e_N, g_NNE: -0.0000034483169191011346
|
||||
e_N, g_NNW: 0.0000034059972640161084
|
||||
e_W, g_WNW: 0.000003405934362501001
|
||||
e_W, g_WSW: -0.00000344858668736309
|
||||
e_S, g_SSW: 0.0000029689592297656908
|
||||
e_S, g_SSE: -0.0000006279732347365118
|
||||
e_E, g_ESE: -0.0000006278110244023648
|
||||
e_E, g_ENE: 0.0000029689801689897473
|
||||
|
||||
=== Distortions of rigid edges (for validation) ===
|
||||
|
||||
These values should be small relative to the ones for the flexible edges
|
||||
|
||||
--- Range ---
|
||||
|
||||
Largest absolute: 0.00000000002916368237382178
|
||||
|
||||
--- Table ---
|
||||
|
||||
a_NE, a_NW: 0.000000000024039999653399018
|
||||
a_NW, a_SW: 0.00000000002451793579782236
|
||||
a_SW, a_SE: -0.000000000028570972470668657
|
||||
a_SE, a_NE: -0.00000000002916368237382178
|
||||
a_NE, b_NE: -0.000000000022712800498073622
|
||||
a_NW, b_NW: 0.0000000000010783395006240168
|
||||
a_SW, b_SW: -0.00000000002146677512286218
|
||||
b_NE, c_N: 0.00000000000907905964233893
|
||||
b_NW, c_N: -0.00000000002003437977280497
|
||||
b_NW, c_W: -0.000000000019747523880603447
|
||||
b_SW, c_W: 0.000000000009824853560213723
|
||||
g_NNE, g_NNW: 0.0000000000003400820265509057
|
||||
g_NNW, g_WNW: -0.0000000000004886127731423908
|
||||
g_WNW, g_WSW: 0.00000000000005762239323369454
|
||||
g_WSW, g_SSW: -0.00000000000020348398264541725
|
||||
g_SSW, g_SSE: -0.0000000000010258984125039788
|
||||
g_SSE, g_ESE: -0.0000000000001306316925624901
|
||||
g_ESE, g_ENE: -0.0000000000011334497459238174
|
||||
g_ENE, g_NNE: -0.00000000000007913265991766227
|
||||
a_SE, a_NW: 0.00000000001299251509560824
|
||||
a_SW, a_NE: -0.000000000019852249047597653
|
||||
a_NW, c_N: 0.00000000000757318396521532
|
||||
b_NW, b_NE: -0.000000000015613313427643198
|
||||
c_N, a_NE: -0.000000000013250324277324116
|
||||
a_NW, b_NE: 0.0000000000145795645528458
|
||||
b_NW, a_NE: 0.000000000004191204809210469
|
||||
a_SW, c_W: -0.000000000012779924576702457
|
||||
b_SW, b_NW: -0.000000000015326928563179278
|
||||
c_W, a_NW: 0.00000000000786836134744787
|
||||
a_SW, b_NW: 0.000000000004368311238549999
|
||||
b_SW, a_NW: 0.00000000001505750069726914
|
||||
g_NNE, g_WNW: 0.0000000000005718276734526309
|
||||
g_NNW, g_WSW: 0.0000000000004788781998985515
|
||||
g_WNW, g_SSW: -0.00000000000035703902510469045
|
||||
g_WSW, g_SSE: 0.0000000000002254652770669901
|
||||
g_SSW, g_ESE: -0.0000000000002515288118811408
|
||||
g_SSE, g_ENE: -0.00000000000030679606642680965
|
||||
g_NNE, g_WSW: 0.0000000000003206128800632269
|
||||
g_NNW, g_SSW: 0.00000000000032846334235664577
|
||||
g_WNW, g_SSE: 0.00000000000012278123026907122
|
||||
g_WSW, g_ESE: 0.00000000000014507654318238083
|
||||
g_SSW, g_ENE: 0.000000000000033599978615832786
|
||||
g_NNE, g_SSW: 0.0000000000001815026882238444
|
||||
g_NNW, g_SSE: 0.0000000000002631474960754007
|
||||
g_WNW, g_ESE: 0.00000000000031684465816238584
|
||||
g_WSW, g_ENE: 0.0000000000002348858318190928
|
||||
g_NNE, g_SSE: 0.00000000000007913265991766227
|
||||
g_NNW, g_ESE: 0.0000000000001438204692154338
|
||||
g_WNW, g_ENE: 0.0000000000004248670193198296
|
||||
g_NNE, g_ESE: 0.00000000000019783164979415566
|
||||
g_NNW, g_ENE: -0.0000000000002364559242777765
|
295
impossolid/twice-augmented_angle-distortions
Normal file
295
impossolid/twice-augmented_angle-distortions
Normal file
|
@ -0,0 +1,295 @@
|
|||
58 triangles
|
||||
|
||||
Triangle a_NE, a_SE, z_E
|
||||
a_NE: 0.0020627780860564826°
|
||||
a_SE: -0.0021197445448706276°
|
||||
z_E: 5.696645881414497e-05°
|
||||
|
||||
Triangle a_NE, b_NE, z_E
|
||||
a_NE: 0.0017363010366011622°
|
||||
b_NE: -0.001956513180971342°
|
||||
z_E: 0.00022021214437017989°
|
||||
|
||||
Triangle a_SE, a_SW, z_S
|
||||
a_SE: -0.0021197448587955137°
|
||||
a_SW: 0.0020627761256122312°
|
||||
z_S: 5.696873318328244e-05°
|
||||
|
||||
Triangle a_SE, b_SE, z_E
|
||||
a_SE: -0.0018856584331388149°
|
||||
b_SE: 0.0011890357645540917°
|
||||
z_E: 0.0006966226686131449°
|
||||
|
||||
Triangle a_SE, b_SE, z_S
|
||||
a_SE: -0.0018856502946889009°
|
||||
b_SE: 0.0011890295778727022°
|
||||
z_S: 0.0006966207168233041°
|
||||
|
||||
Triangle a_SW, b_SW, z_S
|
||||
a_SW: 0.0017363089225312933°
|
||||
b_SW: -0.001956518417863151°
|
||||
z_S: 0.00022020949535317413°
|
||||
|
||||
Triangle b_NE, c_E, y_NE
|
||||
b_NE: -5.4156720231901545e-05°
|
||||
c_E: -0.00040358386964811643°
|
||||
y_NE: 0.00045774058987291255°
|
||||
|
||||
Triangle b_NE, c_E, z_E
|
||||
b_NE: -0.0009184660407299816°
|
||||
c_E: 0.0008739657117544652°
|
||||
z_E: 4.450032897551637e-05°
|
||||
|
||||
Triangle b_NE, c_N, y_NE
|
||||
b_NE: 0.00017470943667774463°
|
||||
c_N: -0.0001747266285079263°
|
||||
y_NE: 1.7191837287100498e-08°
|
||||
|
||||
Triangle b_NW, c_N, y_NW
|
||||
b_NW: 0.003928388803437599°
|
||||
c_N: -0.0039285291447015425°
|
||||
y_NW: 1.4034125683792809e-07°
|
||||
|
||||
Triangle b_NW, c_W, y_NW
|
||||
b_NW: 0.0039283900732698385°
|
||||
c_W: -0.0039285297795643714°
|
||||
y_NW: 1.3970630163839814e-07°
|
||||
|
||||
Triangle b_SE, c_E, y_SE
|
||||
b_SE: -0.000897519700536975°
|
||||
c_E: 0.0002210891647536073°
|
||||
y_SE: 0.0006764305357691569°
|
||||
|
||||
Triangle b_SE, c_E, z_E
|
||||
b_SE: -0.0001661945662831954°
|
||||
c_E: -0.0009587837744717831°
|
||||
z_E: 0.0011249783407549785°
|
||||
|
||||
Triangle b_SE, c_S, y_SE
|
||||
b_SE: -0.0008975178741081891°
|
||||
c_S: 0.00022108969701406522°
|
||||
y_SE: 0.0006764281771083347°
|
||||
|
||||
Triangle b_SE, c_S, z_S
|
||||
b_SE: -0.00016620401637368332°
|
||||
c_S: -0.0009587725587678619°
|
||||
z_S: 0.0011249765751415453°
|
||||
|
||||
Triangle b_SW, c_S, y_SW
|
||||
b_SW: -5.415090214455631e-05°
|
||||
c_S: -0.00040357591168316276°
|
||||
y_SW: 0.00045772681384903535°
|
||||
|
||||
Triangle b_SW, c_S, z_S
|
||||
b_SW: -0.0009184701495854597°
|
||||
c_S: 0.00087398271318051°
|
||||
z_S: 4.448743641916053e-05°
|
||||
|
||||
Triangle b_SW, c_W, y_SW
|
||||
b_SW: 0.00017470839824795803°
|
||||
c_W: -0.0001747249218624347°
|
||||
y_SW: 1.6523628687536984e-08°
|
||||
|
||||
Triangle c_E, d_NE, e_E
|
||||
c_E: -0.0007556600615572506°
|
||||
d_NE: 0.0002641663727089849°
|
||||
e_E: 0.0004914936888269494°
|
||||
|
||||
Triangle c_E, d_NE, y_NE
|
||||
c_E: -0.0003919462083246117°
|
||||
d_NE: -4.2518017124848484e-05°
|
||||
y_NE: 0.00043446422546367103°
|
||||
|
||||
Triangle c_E, d_SE, e_E
|
||||
c_E: 0.00022487539229842923°
|
||||
d_SE: 0.000264262914654978°
|
||||
e_E: -0.0004891383069605126°
|
||||
|
||||
Triangle c_E, d_SE, y_SE
|
||||
c_E: 0.0006690477311224186°
|
||||
d_SE: -0.0004495970440387964°
|
||||
y_SE: -0.000219450687097833°
|
||||
|
||||
Triangle c_N, d_NE, e_N
|
||||
c_N: 0.00043802608161769285°
|
||||
d_NE: 0.0006061756293931353°
|
||||
e_N: -0.0010442017109895119°
|
||||
|
||||
Triangle c_N, d_NE, y_NE
|
||||
c_N: 7.77608707309696e-05°
|
||||
d_NE: 0.0004272013700656885°
|
||||
y_NE: -0.0005049622408037635°
|
||||
|
||||
Triangle c_N, d_NW, e_N
|
||||
c_N: -0.0018371050143599632°
|
||||
d_NW: 0.0006689659636691658°
|
||||
e_N: 0.0011681390506907974°
|
||||
|
||||
Triangle c_N, d_NW, y_NW
|
||||
c_N: -0.004392411525167006°
|
||||
d_NW: 0.0034642502022776966°
|
||||
y_NW: 0.0009281613228964147°
|
||||
|
||||
Triangle c_S, d_SE, e_S
|
||||
c_S: 0.00022490750998827025°
|
||||
d_SE: 0.00026425064935864384°
|
||||
e_S: -0.0004891581593469141°
|
||||
|
||||
Triangle c_S, d_SE, y_SE
|
||||
c_S: 0.0006690562241331577°
|
||||
d_SE: -0.000449587257172368°
|
||||
y_SE: -0.00021946896695368423°
|
||||
|
||||
Triangle c_S, d_SW, e_S
|
||||
c_S: -0.0007556856092989506°
|
||||
d_SW: 0.0002641521543509384°
|
||||
e_S: 0.0004915334549480121°
|
||||
|
||||
Triangle c_S, d_SW, y_SW
|
||||
c_S: -0.0003919572288921813°
|
||||
d_SW: -4.252978876451152e-05°
|
||||
y_SW: 0.00043448701768511455°
|
||||
|
||||
Triangle c_W, d_NW, e_W
|
||||
c_W: -0.0018371356879498535°
|
||||
d_NW: 0.0006689415152791867°
|
||||
e_W: 0.0011681941726706668°
|
||||
|
||||
Triangle c_W, d_NW, y_NW
|
||||
c_W: -0.00439242709246912°
|
||||
d_NW: 0.00346423653491712°
|
||||
y_NW: 0.000928190557552°
|
||||
|
||||
Triangle c_W, d_SW, e_W
|
||||
c_W: 0.0004380758375859273°
|
||||
d_SW: 0.0006061529123826404°
|
||||
e_W: -0.0010442287499685676°
|
||||
|
||||
Triangle c_W, d_SW, y_SW
|
||||
c_W: 7.777468017877709e-05°
|
||||
d_SW: 0.00042721382367005845°
|
||||
y_SW: -0.0005049885038488355°
|
||||
|
||||
Triangle d_NE, e_E, f_NE
|
||||
d_NE: 0.00038569630375207°
|
||||
e_E: -4.1012391825745453e-05°
|
||||
f_NE: -0.0003446839119192191°
|
||||
|
||||
Triangle d_NE, e_N, f_NE
|
||||
d_NE: 3.4118590889420375e-05°
|
||||
e_N: -0.0005253562237612641°
|
||||
f_NE: 0.0004912376328576329°
|
||||
|
||||
Triangle d_NW, e_N, f_NW
|
||||
d_NW: 0.0012793501149417352°
|
||||
e_N: -0.0003005889518448157°
|
||||
f_NW: -0.0009787611630969195°
|
||||
|
||||
Triangle d_NW, e_W, f_NW
|
||||
d_NW: 0.0012793645837376744°
|
||||
e_W: -0.00030057569104258164°
|
||||
f_NW: -0.0009787888926879873°
|
||||
|
||||
Triangle d_SE, e_E, f_SE
|
||||
d_SE: -7.914704212907964e-06°
|
||||
e_E: -0.00026442283958516555°
|
||||
f_SE: 0.0002723375437980735°
|
||||
|
||||
Triangle d_SE, e_S, f_SE
|
||||
d_SE: -7.92374907376825e-06°
|
||||
e_S: -0.00026443091589101186°
|
||||
f_SE: 0.0002723546649647801°
|
||||
|
||||
Triangle d_SW, e_S, f_SW
|
||||
d_SW: 0.0003857085871175059°
|
||||
e_S: -4.10046320098445e-05°
|
||||
f_SW: -0.00034470395510055596°
|
||||
|
||||
Triangle d_SW, e_W, f_SW
|
||||
d_SW: 3.4104280807412124e-05°
|
||||
e_W: -0.0005253692789679576°
|
||||
f_SW: 0.0004912649981676509°
|
||||
|
||||
Triangle e_E, f_NE, g_ENE
|
||||
e_E: -0.00015088143299379908°
|
||||
f_NE: 0.0001553185337925811°
|
||||
g_ENE: -4.437100798782012e-06°
|
||||
|
||||
Triangle e_E, f_SE, g_ESE
|
||||
e_E: -5.289010589137888e-05°
|
||||
f_SE: -5.705811280876105e-05°
|
||||
g_ESE: 0.00010994821870013993°
|
||||
|
||||
Triangle e_E, g_ENE, g_ESE
|
||||
e_E: -7.744546709176348e-05°
|
||||
g_ENE: -0.000139748678492424°
|
||||
g_ESE: 0.0002171941456126092°
|
||||
|
||||
Triangle e_N, f_NE, g_NNE
|
||||
e_N: -0.00011644664380128233°
|
||||
f_NE: -0.0002467109250190447°
|
||||
g_NNE: 0.000363157568820327°
|
||||
|
||||
Triangle e_N, f_NW, g_NNW
|
||||
e_N: -0.0005663172445693476°
|
||||
f_NW: 0.00012971776202874707°
|
||||
g_NNW: 0.000436599482547706°
|
||||
|
||||
Triangle e_N, g_NNE, g_NNW
|
||||
e_N: 1.3987573481699656e-06°
|
||||
g_NNE: 0.0003394089509995979°
|
||||
g_NNW: -0.00034080770834776786°
|
||||
|
||||
Triangle e_S, f_SE, g_SSE
|
||||
e_S: -5.28844724030364e-05°
|
||||
f_SE: -5.706849415076931e-05°
|
||||
g_SSE: 0.00010995296653959485°
|
||||
|
||||
Triangle e_S, f_SW, g_SSW
|
||||
e_S: -0.00015088330234647174°
|
||||
f_SW: 0.00015531752390529618°
|
||||
g_SSW: -4.434221558824447e-06°
|
||||
|
||||
Triangle e_S, g_SSE, g_SSW
|
||||
e_S: -7.743940860649445e-05°
|
||||
g_SSE: 0.00021719812617959633°
|
||||
g_SSW: -0.00013975871755889102°
|
||||
|
||||
Triangle e_W, f_NW, g_WNW
|
||||
e_W: -0.0005663163395084325°
|
||||
f_NW: 0.00012971358477642525°
|
||||
g_WNW: 0.00043660275473200727°
|
||||
|
||||
Triangle e_W, f_SW, g_WSW
|
||||
e_W: -0.00011643403040295652°
|
||||
f_SW: -0.000246728634124338°
|
||||
g_WSW: 0.0003631626645272945°
|
||||
|
||||
Triangle e_W, g_WNW, g_WSW
|
||||
e_W: 1.4097619143171869e-06°
|
||||
g_WNW: -0.00034082347526265266°
|
||||
g_WSW: 0.0003394137133483355°
|
||||
|
||||
Triangle f_NE, g_ENE, g_NNE
|
||||
f_NE: 7.450149718835064e-05°
|
||||
g_ENE: -0.00013744180584041032°
|
||||
g_NNE: 6.294030865205968e-05°
|
||||
|
||||
Triangle f_NW, g_NNW, g_WNW
|
||||
f_NW: 0.00023868980004237983°
|
||||
g_NNW: -0.00011934547999459255°
|
||||
g_WNW: -0.00011934432004778728°
|
||||
|
||||
Triangle f_SE, g_ESE, g_SSE
|
||||
f_SE: 3.87570213717936e-05°
|
||||
g_ESE: -1.9378552060800303e-05°
|
||||
g_SSE: -1.937846930388787e-05°
|
||||
|
||||
Triangle f_SW, g_SSW, g_WSW
|
||||
f_SW: 7.450129267994043e-05°
|
||||
g_SSW: -0.00013743845931912801°
|
||||
g_WSW: 6.293716665339844e-05°
|
||||
|
||||
Total angle distortion: 0.11233054610809035°
|
||||
Highest angle distortion: 0.0039283900732698385°
|
||||
Lowest angle distortion: -0.00439242709246912°
|
98
impossolid/twice-augmented_edge-distortions
Normal file
98
impossolid/twice-augmented_edge-distortions
Normal file
|
@ -0,0 +1,98 @@
|
|||
a_SE, b_SE: 0.000015249448583054653
|
||||
b_SW, c_S: 0.000006918255000202575
|
||||
b_SE, c_S: 0.00001022525369434997
|
||||
b_SE, c_E: 0.000010225282824746383
|
||||
b_NE, c_E: 0.000006918450075555058
|
||||
z_S, a_SW: -0.0000219346808875234
|
||||
z_S, a_SE: 0.00002021118621352795
|
||||
z_E, a_SE: 0.00002021122888534378
|
||||
z_E, a_NE: -0.00002193465480671757
|
||||
z_S, b_SW: 0.000015276737515369292
|
||||
z_S, b_SE: -0.000010771908316892743
|
||||
z_E, b_SE: -0.00001077200999765046
|
||||
z_E, b_NE: 0.000015276631362360217
|
||||
z_S, c_S: -0.0000027853351723499016
|
||||
z_E, c_E: -0.000002785228607191555
|
||||
c_N, d_NE: -0.000007632775579087326
|
||||
c_N, d_NW: 0.00001402754980516112
|
||||
c_W, d_NW: 0.000014028001282264439
|
||||
c_W, d_SW: -0.00000763316944431703
|
||||
c_S, d_SW: 0.000006566974972180328
|
||||
c_S, d_SE: -0.0000033161321458747414
|
||||
c_E, d_SE: -0.00000331586236646513
|
||||
c_E, d_NE: 0.000006566624318564243
|
||||
y_NE, b_NE: -0.0000017608392620486498
|
||||
y_NW, b_NW: -0.00003959022952266363
|
||||
y_SW, b_SW: -0.0000017608153313274316
|
||||
y_SE, b_SE: 0.000005637007821097203
|
||||
y_NE, c_N: 0.000001760310254250749
|
||||
y_NW, c_N: 0.00003958128591112948
|
||||
y_NW, c_W: 0.000039581305103782685
|
||||
y_SW, c_W: 0.0000017603065237110672
|
||||
y_SW, c_S: 0.0000017602552603493003
|
||||
y_SE, c_S: -0.00000563497752606038
|
||||
y_SE, c_E: -0.0000056349905677193694
|
||||
y_NE, c_E: 0.0000017602528935919282
|
||||
y_NE, d_NE: -0.0000017608481082635805
|
||||
y_NW, d_NW: -0.0000395891283971962
|
||||
y_SW, d_SW: -0.0000017608381747596222
|
||||
y_SE, d_SE: 0.0000056371661583272735
|
||||
d_NE, e_N: 0.000007303314580670295
|
||||
d_NW, e_N: -0.000016255656816635924
|
||||
d_NW, e_W: -0.000016256069869023512
|
||||
d_SW, e_W: 0.00000730369455466398
|
||||
d_SW, e_S: -0.000006000901856373712
|
||||
d_SE, e_S: 0.000003879307405619109
|
||||
d_SE, e_E: 0.000003879053499059208
|
||||
d_NE, e_E: -0.00000600059436381427
|
||||
c_N, e_N: 0.00000899767908293228
|
||||
c_W, e_W: 0.000008997328779446816
|
||||
c_S, e_S: 0.0000042757526759396545
|
||||
c_E, e_E: 0.000004275945999382972
|
||||
e_N, f_NE: 0.0000026971057195376348
|
||||
e_N, f_NW: 0.000006498321003978716
|
||||
e_W, f_NW: 0.000006498333167484994
|
||||
e_W, f_SW: 0.000002697065747495785
|
||||
e_S, f_SW: 0.000001359196116957704
|
||||
e_S, f_SE: 0.0000010550443264554641
|
||||
e_E, f_SE: 0.0000010550540852081317
|
||||
e_E, f_NE: 0.000001359177866673992
|
||||
d_NE, f_NE: -0.0000029405886467824407
|
||||
d_NW, f_NW: -0.000009421855439304757
|
||||
d_SW, f_SW: -0.000002940615976753832
|
||||
d_SE, f_SE: -0.000001529705558996715
|
||||
f_NE, g_ENE: -0.00000011649787286240574
|
||||
f_NE, g_NNE: -0.000002135681696645076
|
||||
f_NW, g_NNW: -0.000003607774033318148
|
||||
f_NW, g_WNW: -0.000003607785721714447
|
||||
f_SW, g_WSW: -0.0000021356459140809334
|
||||
f_SW, g_SSW: -0.00000011652747271646458
|
||||
f_SE, g_SSE: -0.0000005858121892925972
|
||||
f_SE, g_ESE: -0.0000005858113552594831
|
||||
e_N, g_NNE: -0.0000034483169191011346
|
||||
e_N, g_NNW: 0.0000034059972640161084
|
||||
e_W, g_WNW: 0.000003405934362501001
|
||||
e_W, g_WSW: -0.00000344858668736309
|
||||
e_S, g_SSW: 0.0000029689592297656908
|
||||
e_S, g_SSE: -0.0000006279732347365118
|
||||
e_E, g_ESE: -0.0000006278110244023648
|
||||
e_E, g_ENE: 0.0000029689801689897473
|
||||
a_NE, a_NW
|
||||
a_NW, a_SW
|
||||
a_SW, a_SE
|
||||
a_SE, a_NE
|
||||
a_NE, b_NE
|
||||
a_NW, b_NW
|
||||
a_SW, b_SW
|
||||
b_NE, c_N
|
||||
b_NW, c_N
|
||||
b_NW, c_W
|
||||
b_SW, c_W
|
||||
g_NNE, g_NNW
|
||||
g_NNW, g_WNW
|
||||
g_WNW, g_WSW
|
||||
g_WSW, g_SSW
|
||||
g_SSW, g_SSE
|
||||
g_SSE, g_ESE
|
||||
g_ESE, g_ENE
|
||||
g_ENE, g_NNE
|
38
impossolid/twice-augmented_vertices
Normal file
38
impossolid/twice-augmented_vertices
Normal file
|
@ -0,0 +1,38 @@
|
|||
a_NE: 0.4974660839869507, 0.5025284618118182, -0.21962917587407324
|
||||
a_NW: -0.5025160085784002, 0.5025084403663106, -0.21364467368968995
|
||||
a_SW: -0.5025317897634418, -0.4974736643225916, -0.21962716242129268
|
||||
a_SE: 0.49745030267915796, -0.4974536427543331, -0.22561166444858374
|
||||
z_S: 0.0023385661484333744, -0.22870402619169428, 0.60063190420276
|
||||
z_E: 0.22870024445875012, -0.0023413854336990325, 0.6006314485234188
|
||||
b_NE: 0.8118652156106724, 0.8061651522670251, 0.6797917189944392
|
||||
b_NW: -0.8061397981609031, 0.8061327572110616, 0.6894748470124282
|
||||
b_SW: -0.8061653323313128, -0.8118722761768307, 0.679794976829472
|
||||
b_SE: 0.8117686673287107, -0.8117688670778128, 0.6701787153604973
|
||||
y_NE: 0.1103960413184542, 0.10342511854710223, 0.798509539299725
|
||||
y_NW: -0.10337789916924411, 0.1033740688261596, 0.7998232055607494
|
||||
y_SW: -0.10342804260149929, -0.11039987437192703, 0.7985099696006345
|
||||
y_SE: 0.11038804399025821, -0.11039097027269067, 0.7972438212830046
|
||||
c_N: 0.006192472465608106, 0.9938029259455414, 1.2416489044968044
|
||||
c_W: -0.9938054007689278, -0.006199199673009326, 1.2416509179495838
|
||||
c_S: 0.006109939936188693, -1.0059122097709343, 1.229859721030557
|
||||
c_E: 1.0059097110061566, -0.00610818737102383, 1.2298577082098059
|
||||
d_NE: 0.19998199287503826, 0.18129904829618806, 1.7914377777202868
|
||||
d_NW: -0.18132979121792334, 0.1813276309223748, 1.7936881702060035
|
||||
d_SW: -0.18129959231726273, -0.19998415749541185, 1.791438545222019
|
||||
d_SE: 0.1999582803508571, -0.1999588290387209, 1.7891944479793136
|
||||
e_N: 0.011969023209503969, 1.0551851488412447, 2.239755536903205
|
||||
e_W: -1.0551855894711406, -0.011973997889437291, 2.2397576852440584
|
||||
e_S: 0.011933151451289365, -1.0790685618433953, 2.2271674919335998
|
||||
e_E: 1.0790680956836711, -0.011929083518777098, 2.2271653437223433
|
||||
f_NE: 0.29554147977141343, 0.26516582064069727, 2.7833192564200235
|
||||
f_NW: -0.26515631709994025, 0.26515579997276006, 2.786626792661052
|
||||
f_SW: -0.26516396217611815, -0.2955420036217133, 2.783320385102162
|
||||
f_SE: 0.2955327295186172, -0.29553087779401516, 2.780016555503281
|
||||
g_NNE: 0.5169980642139731, 1.1901085117178565, 3.092242755151354
|
||||
g_NNW: -0.4829845300027995, 1.1900889935835326, 3.0981428299427223
|
||||
g_WNW: -1.190089809078002, 0.4829807102891247, 3.0981442533320376
|
||||
g_WSW: -1.1901050905533348, -0.5170018958762016, 3.0922461915171433
|
||||
g_SSW: -0.48302142275001, -1.2240825763590955, 3.083903649106097
|
||||
g_SSE: 0.516961171466923, -1.224063058223441, 3.0780035743129184
|
||||
g_ESE: 1.224066450541603, -0.516954774929556, 3.078002150923603
|
||||
g_ENE: 1.2240817320182662, 0.4830278312359312, 3.083900212740308
|
Loading…
Add table
Add a link
Reference in a new issue