From cb90af4fb71e4ff95c959cd4492b3a7608d587e0 Mon Sep 17 00:00:00 2001 From: allem Date: Wed, 4 Apr 2018 15:24:16 -0400 Subject: [PATCH] implemented 4-simplex intersections --- Tetrahedrons/MVec4D.cs | 10 ++- Tetrahedrons/Simplex.cs | 136 +++++++++++++++++++++--------- Tetrahedrons/TetrahedronWindow.cs | 60 ++++++------- 3 files changed, 133 insertions(+), 73 deletions(-) diff --git a/Tetrahedrons/MVec4D.cs b/Tetrahedrons/MVec4D.cs index bfb056b..9a0d8aa 100644 --- a/Tetrahedrons/MVec4D.cs +++ b/Tetrahedrons/MVec4D.cs @@ -988,7 +988,8 @@ namespace Tetrahedrons public static MVec4D Outer(double c, MVec4D n) => Mul(c, n); - + public static MVec4D Transform(MVec4D m, MVec4D t) => Mul(Mul(t, m), t.Rev); + public static MVec4D? Add(MVec4D? m, MVec4D? n) => m.HasValue && n.HasValue ? (MVec4D?) Add(m.Value, n.Value) : null; public static MVec4D? Add(MVec4D? m, double? n) => m.HasValue && n.HasValue ? (MVec4D?) Add(m.Value, n.Value) : null; public static MVec4D? Add(double? m, MVec4D? n) => n.HasValue && m.HasValue ? (MVec4D?) Add(m.Value, n.Value) : null; @@ -1013,6 +1014,8 @@ namespace Tetrahedrons public static MVec4D? Outer(MVec4D? m, double? n) => m.HasValue && n.HasValue ? (MVec4D?) Outer(m.Value, n.Value) : null; public static MVec4D? Outer(double? m, MVec4D? n) => n.HasValue && m.HasValue ? (MVec4D?) Outer(m.Value, n.Value) : null; + public static MVec4D? Transform(MVec4D? m, MVec4D? t) => Mul(Mul(t, m), t?.Rev); + #endregion #region Operators @@ -1037,6 +1040,9 @@ namespace Tetrahedrons public static MVec4D operator ^(MVec4D m, double c) => Outer(m, c); public static MVec4D operator ^(double c, MVec4D n) => Outer(c, n); + public static MVec4D operator |(MVec4D m, MVec4D t) => Transform(m, t); + + public static MVec4D? operator +(MVec4D? m, MVec4D? n) => Add(m, n); public static MVec4D? operator +(double? c, MVec4D? n) => Add(c, n); public static MVec4D? operator +(MVec4D? m, double? c) => Add(m, c); @@ -1057,7 +1063,9 @@ namespace Tetrahedrons public static MVec4D? operator ^(MVec4D? m, double? c) => Outer(m, c); public static MVec4D? operator ^(double? c, MVec4D? n) => Outer(c, n); + public static MVec4D? operator |(MVec4D? m, MVec4D? t) => Transform(m, t); + public static MVec4D operator -(MVec4D m) => m.Neg; public static MVec4D? operator ~(MVec4D m) => m.Inv; public static MVec4D operator !(MVec4D m) => m.Rev; diff --git a/Tetrahedrons/Simplex.cs b/Tetrahedrons/Simplex.cs index 1fc6e42..13d9cc1 100644 --- a/Tetrahedrons/Simplex.cs +++ b/Tetrahedrons/Simplex.cs @@ -1,5 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; +using System.Net.Mail; namespace Tetrahedrons { @@ -7,14 +9,42 @@ namespace Tetrahedrons { public MVec4D[] Verts; + public int[] Faces; + public int[] Edjes; + public Simplex(IEnumerable verts) + : this(verts.ToArray()) { - Verts = verts.ToArray(); } public Simplex(params MVec4D[] verts) { - Verts = verts; + Verts = verts.ToArray(); + + var e = new List(); + for (var i = 0; i < Verts.Length; i++) + for (var j = i + 1; j < Verts.Length; j++) + { + e.Add(i); + e.Add(j); + } + + Edjes = e.ToArray(); + + Faces = new int[0]; + } + + public Simplex(IEnumerable verts, IEnumerable faces) + : this(verts) + { + Faces = faces.ToArray(); + } + + public Simplex(IEnumerable verts, IEnumerable faces, IEnumerable edges) + { + Verts = verts.ToArray(); + Faces = faces.ToArray(); + Edjes = edges.ToArray(); } public bool[] Sides(MVec4D blade, MVec4D pivot) @@ -41,50 +71,78 @@ namespace Tetrahedrons { var sides = Sides(blade, pivot); var verts = new List(); + var edges = new List(); + + var face_verts = new List[Verts.Length]; + for (var i = 0; i < face_verts.Length; i++) + face_verts[i] = new List(); - for (var i = 0; i < Verts.Length; i++) - for (var j = i + 1; j < Verts.Length; j++) { - if (sides[i] == sides[j]) continue; - var m = Verts[i] - pivot; - var n = Verts[j] - pivot; + var k = 0; + for (var i = 0; i < Verts.Length; i++) + for (var j = i + 1; j < Verts.Length; j++) + { + if (sides[i] == sides[j]) continue; + var m = Verts[i] - pivot; + var n = Verts[j] - pivot; - var v = m - n; - var alph = (blade ^ m) * ~(blade ^ v); - if (!alph.HasValue) continue; - var p = m - v * alph.Value; - verts.Add(p); + var v = m - n; + var alph = (blade ^ m) * ~(blade ^ v); + if (!alph.HasValue) continue; + var p = m - v * alph.Value; + + verts.Add(p); + face_verts[i].Add(k); + face_verts[j].Add(k); + + k++; + } } - return new Simplex(verts); - } - - public int[] Faces() - { - switch (Verts.Length) + var faces = new List(); + foreach (var vlst in face_verts) { - case 3: - return new[] {0, 1, 2}; - case 4: - return new[] - { - 0, 1, 2, - 0, 1, 3, - 0, 2, 3, - 1, 2, 3 - }; - case 6: - return new[] - { - 0, 2, 4 - // todo: vertices of a face must be on lines which share a vertex in the simplex - // that's the pattern, and why it "just works" for the 3-simplex. - // think of it as truncating the embedded simplex - }; + for (var i = 0; i < vlst.Count - 2; i++) + for (var j = i + 1; j < vlst.Count - 1; j++) + for (var k = j + 1; k < vlst.Count; k++) + { + faces.Add(vlst[i]); + faces.Add(vlst[j]); + faces.Add(vlst[k]); - default: - return new int[0]; + edges.Add(vlst[i]); + edges.Add(vlst[j]); + edges.Add(vlst[j]); + edges.Add(vlst[k]); + edges.Add(vlst[k]); + edges.Add(vlst[i]); + } } + + if (faces.Count == 6) + { + for (var i = 0; i < 3; i++) + { + var a = faces[i]; + var b = faces[(1 + i) % 3]; + var c = faces[3 + i]; + var d = faces[3 + (1 + i) % 3]; + + faces.Add(c); + faces.Add(a); + faces.Add(b); + faces.Add(b); + faces.Add(d); + faces.Add(c); + + edges.Add(a); + edges.Add(c); + edges.Add(b); + edges.Add(d); + } + } + + return new Simplex(verts, faces, edges); } } } \ No newline at end of file diff --git a/Tetrahedrons/TetrahedronWindow.cs b/Tetrahedrons/TetrahedronWindow.cs index 124e9da..12521c0 100644 --- a/Tetrahedrons/TetrahedronWindow.cs +++ b/Tetrahedrons/TetrahedronWindow.cs @@ -27,6 +27,7 @@ namespace Tetrahedrons private Simplex _intr; private double _t; + private bool _pause; protected override void OnLoad(EventArgs e) { @@ -62,44 +63,30 @@ namespace Tetrahedrons GL.MatrixMode(MatrixMode.Modelview); GL.LoadMatrix(ref _view); - GL.Begin(PrimitiveType.TriangleStrip); - GL.Color3(1d, 1, 1); - Util.Vertex3(-_a - _b); - Util.Vertex3(-_a + _b); - Util.Vertex3(_a - _b); - Util.Vertex3(_a + _b); + GL.Enable(EnableCap.DepthTest); + + GL.Begin(PrimitiveType.Lines); + GL.Color3(0f, 0, 0); + foreach (var f in _intr.Edjes) + Util.Vertex3(_intr.Verts[f]); GL.End(); - GL.Enable(EnableCap.DepthTest); GL.Begin(PrimitiveType.Triangles); - foreach (var f in _intr.Faces()) + foreach (var f in _intr.Faces) { Util.Color3(_intr.Verts[f]); Util.Vertex3(_intr.Verts[f]); } + GL.End(); GL.Disable(EnableCap.DepthTest); - GL.Begin(PrimitiveType.Points); - foreach (var m in _pent.Verts) - Util.Vertex4(m); - GL.End(); - GL.Begin(PrimitiveType.Lines); - for (var i = 0; i < _pent.Verts.Length; i++) - for (var j = i + 1; j < _pent.Verts.Length; j++) - { - Util.Vertex4(_pent.Verts[i]); - Util.Vertex4(_pent.Verts[j]); - } + foreach (var f in _pent.Edjes) + Util.Vertex4(_pent.Verts[f]); GL.End(); - GL.Begin(PrimitiveType.Points); - foreach (var m in _intr.Verts) - Util.Vertex4(m); - GL.End(); - SwapBuffers(); } @@ -109,22 +96,29 @@ namespace Tetrahedrons _proj3d = Matrix4.CreateOrthographic(6, 6f * Height / Width, -4, 4); + if (_pause) return; + _t += e.Time; - var pln = MVec4D.UnitXy + MVec4D.UnitZw; - + var pln = .5 * MVec4D.UnitXy + MVec4D.UnitZw; var r = MVec4D.Rotor(e.Time / 10, pln.Normalized); for (var i = 0; i < _pent.Verts.Length; i++) - { - var m = _pent.Verts[i]; - m = r * m * !r; - _pent.Verts[i] = m; - } + _pent.Verts[i] |= r; var blade = MVec4D.UnitXyz; -// var pivot = .5 * MVec4D.UnitW; - var pivot = 1.1 * Math.Sin(_t) * MVec4D.UnitW; + var pivot = MVec4D.Zero; + + pivot = .9 * Math.Sin(_t / 5) * MVec4D.UnitW; + _intr = _pent.Intersect(blade, pivot); } + + protected override void OnKeyDown(KeyboardKeyEventArgs e) + { + base.OnKeyDown(e); + + if (e.Key == Key.Space) + _pause = !_pause; + } } } \ No newline at end of file