buggy 4-simplex intersections

This commit is contained in:
2018-04-04 14:06:57 -04:00
parent 632172e876
commit 06096bf1aa
5 changed files with 181 additions and 49 deletions

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Dynamic;
using System.Runtime.CompilerServices;
using System.Runtime.Remoting.Messaging;
using System.Text;
using OpenTK;
@@ -42,6 +43,8 @@ namespace Tetrahedrons
public double Norm => Math.Sqrt(Norm2);
public MVec4D Normalized => this * (1 / Norm);
public MVec4D Grade(int k)
{
switch (k)
@@ -929,12 +932,8 @@ namespace Tetrahedrons
);
}
public static MVec4D? Div(MVec4D m, MVec4D n) => Mul(m, n.Inv);
public static MVec4D Div(MVec4D m, double c) => Mul(m, 1 / c);
public static MVec4D? Div(double c, MVec4D n) => Mul(c, n.Inv);
public static MVec4D Inner(MVec4D m, MVec4D n)
{
var m0 = m.Grade(0);
@@ -1030,10 +1029,6 @@ namespace Tetrahedrons
public static MVec4D operator *(double c, MVec4D n) => Mul(c, n);
public static MVec4D operator *(MVec4D m, double c) => Mul(m, c);
public static MVec4D? operator /(MVec4D m, MVec4D n) => Div(m, n);
public static MVec4D? operator /(double c, MVec4D n) => Div(c, n);
public static MVec4D operator /(MVec4D m, double c) => Div(m, c);
public static MVec4D operator &(MVec4D m, MVec4D n) => Inner(m, n);
public static MVec4D operator &(MVec4D m, double c) => Inner(m, c);
public static MVec4D operator &(double c, MVec4D n) => Inner(c, n);
@@ -1054,10 +1049,6 @@ namespace Tetrahedrons
public static MVec4D? operator *(double? c, MVec4D? n) => Mul(c, n);
public static MVec4D? operator *(MVec4D? m, double? c) => Mul(m, c);
public static MVec4D? operator /(MVec4D? m, MVec4D? n) => Div(m, n);
public static MVec4D? operator /(double? c, MVec4D? n) => Div(c, n);
public static MVec4D? operator /(MVec4D? m, double? c) => Div(m, c);
public static MVec4D? operator &(MVec4D? m, MVec4D? n) => Inner(m, n);
public static MVec4D? operator &(MVec4D? m, double? c) => Inner(m, c);
public static MVec4D? operator &(double? c, MVec4D? n) => Inner(c, n);

90
Tetrahedrons/Simplex.cs Normal file
View File

@@ -0,0 +1,90 @@
using System.Collections.Generic;
using System.Linq;
namespace Tetrahedrons
{
public class Simplex
{
public MVec4D[] Verts;
public Simplex(IEnumerable<MVec4D> verts)
{
Verts = verts.ToArray();
}
public Simplex(params MVec4D[] verts)
{
Verts = verts;
}
public bool[] Sides(MVec4D blade, MVec4D pivot)
{
var sides = new bool[Verts.Length];
var perp = blade.Dual;
for (var i = 0; i < Verts.Length; i++)
{
var m = Verts[i];
var p = m - pivot;
var rej = (p ^ blade) * ~blade;
if (!rej.HasValue) continue;
var dot = rej & perp;
sides[i] = dot.Value.S > 0;
}
return sides;
}
public Simplex Intersect(MVec4D blade, MVec4D pivot)
{
var sides = Sides(blade, pivot);
var verts = new List<MVec4D>();
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);
}
return new Simplex(verts);
}
public int[] Faces()
{
switch (Verts.Length)
{
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
};
default:
return new int[0];
}
}
}
}

View File

@@ -1,13 +1,17 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.PerformanceData;
using System.Drawing;
using System.Drawing.Printing;
using System.Net;
using System.Net.Mail;
using System.Runtime.InteropServices.ComTypes;
using System.Security;
using System.Xml.XPath;
using OpenTK;
using OpenTK.Audio.OpenAL;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
using OpenTK.Platform.Windows;
namespace Tetrahedrons
{
@@ -16,10 +20,13 @@ namespace Tetrahedrons
private Matrix4 _proj3d;
private Matrix4 _view;
MVec4D a = MVec4D.UnitX;
MVec4D b = MVec4D.UnitY;
MVec4D v = MVec4D.Vec1(1, 1, 0, -1);
MVec4D t = MVec4D.Vec1(0, 0, 0, 1);
private MVec4D _a = MVec4D.UnitX;
private MVec4D _b = MVec4D.UnitY;
private Simplex _pent;
private Simplex _intr;
private double _t;
protected override void OnLoad(EventArgs e)
{
@@ -28,8 +35,14 @@ namespace Tetrahedrons
X = (DisplayDevice.Default.Width - Width) / 2;
Y = (DisplayDevice.Default.Height - Height) / 2;
_view = Matrix4.LookAt(Vector3.Zero, -new Vector3(1, 1, 1), Vector3.UnitZ);
_view = Matrix4.LookAt(Vector3.Zero, -new Vector3(.86f, .5f, 1), Vector3.UnitZ);
_pent = new Simplex( // not-quite-regular pentatope
new Vector4d(1, -1, -1, -1),
new Vector4d(-1, 1, -1, -1),
new Vector4d(-1, -1, 1, -1),
new Vector4d(-1, -1, -1, 1),
new Vector4d(1, 1, 1, 1));
}
protected override void OnRenderFrame(FrameEventArgs e)
@@ -39,7 +52,6 @@ namespace Tetrahedrons
GL.Viewport(ClientRectangle);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Enable(EnableCap.DepthTest);
GL.PointSize(10f);
GL.LineWidth(3f);
@@ -50,41 +62,42 @@ namespace Tetrahedrons
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref _view);
GL.Disable(EnableCap.DepthTest);
GL.Begin(PrimitiveType.TriangleStrip);
GL.Color3(1d, 1, 1);
GL.Vertex3((-a - b).V3);
GL.Vertex3((-a + b).V3);
GL.Vertex3((a - b).V3);
GL.Vertex3((a + b).V3);
Util.Vertex3(-_a - _b);
Util.Vertex3(-_a + _b);
Util.Vertex3(_a - _b);
Util.Vertex3(_a + _b);
GL.End();
GL.Enable(EnableCap.DepthTest);
GL.Begin(PrimitiveType.Lines);
GL.Color3(1d,0,0); GL.Vertex3(0,0,0); GL.Vertex3(1,0,0);
GL.Color3(0,1d,0); GL.Vertex3(0,0,0); GL.Vertex3(0,1,0);
GL.Color3(0,0,1d); GL.Vertex3(0,0,0); GL.Vertex3(0,0,1);
GL.Begin(PrimitiveType.Triangles);
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();
var B = MVec4D.UnitXyz;
var bt = B ^ t;
var bv = B ^ v;
var alph = bt / bv ?? MVec4D.Zero;
var dt = alph * v;
var p = t - dt;
Console.Out.WriteLine("p = {0}", p);
GL.Begin(PrimitiveType.Lines);
GL.Color3(.5 + t.W/4, 0, .5 - t.W/4);
GL.Vertex3(t.V3);
GL.Color3(.5 + (t + v).W/4, 0, .5 - (t + v).W/4);
GL.Vertex3((t + v).V3);
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]);
}
GL.End();
GL.Begin(PrimitiveType.Points);
GL.Color3(0d, 0, 1);
GL.Vertex3(p.V3);
foreach (var m in _intr.Verts)
Util.Vertex4(m);
GL.End();
SwapBuffers();
@@ -94,13 +107,24 @@ namespace Tetrahedrons
{
base.OnUpdateFrame(e);
_proj3d = Matrix4.CreateOrthographic(6, 6f * Height / Width, -2, 2);
_proj3d = Matrix4.CreateOrthographic(6, 6f * Height / Width, -4, 4);
var rv = MVec4D.Rotor(e.Time, MVec4D.UnitXy);
v = rv * v * !rv;
_t += e.Time;
var rt = MVec4D.Rotor(e.Time / 4, MVec4D.UnitZw);
t = rt * t * !rt;
var pln = 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;
}
var blade = MVec4D.UnitXyz;
// var pivot = .5 * MVec4D.UnitW;
var pivot = 1.1 * Math.Sin(_t) * MVec4D.UnitW;
_intr = _pent.Intersect(blade, pivot);
}
}
}

View File

@@ -45,7 +45,9 @@
<Compile Include="MVec4D.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Simplex.cs" />
<Compile Include="TetrahedronWindow.cs" />
<Compile Include="Util.cs" />
</ItemGroup>
<ItemGroup>
<None Include="OpenTK.dll.config" />

25
Tetrahedrons/Util.cs Normal file
View File

@@ -0,0 +1,25 @@
using OpenTK.Graphics.OpenGL;
namespace Tetrahedrons
{
public static class Util
{
public static void Color3(MVec4D m)
{
m *= .5;
GL.Color3(.5 + m.X, .5 + m.Y, .5 * m.Z);
}
public static void Vertex4(MVec4D m)
{
var i = m.W / 2;
GL.Color3(.5 + i, 0, .5 - i);
GL.Vertex3(m.X, m.Y, m.Z);
}
public static void Vertex3(MVec4D m)
{
GL.Vertex3(m.X, m.Y, m.Z);
}
}
}