This commit is contained in:
2026-05-13 23:02:02 +07:00
parent 5025383676
commit 93da00c206
885 changed files with 980996 additions and 1987 deletions

View File

@@ -0,0 +1,256 @@
/*
The MIT License (MIT)
Copyright (c) 2013-2015 Mikola Lysenko
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
using System;
namespace DA_Assets.SVGMeshUnity.Internals.Cdt2d
{
public static class BinarySearch
{
// https://github.com/mikolalysenko/binary-search-bounds
public interface IComparer<G, E>
{
int Compare(G x, E y);
}
public static int GE<G, E>(G[] a, E y, IComparer<G, E> c, int l, int h)
{
var i = h + 1;
while (l <= h)
{
var m = (int) (uint) (l + h) >> 1;
var x = a[m];
if (c.Compare(x, y) >= 0)
{
i = m;
h = m - 1;
}
else
{
l = m + 1;
}
}
return i;
}
public static int GE<G>(G[] a, G y, int l, int h) where G : IComparable<G>
{
var i = h + 1;
while (l <= h)
{
var m = (int) (uint) (l + h) >> 1;
var x = a[m];
if (x.CompareTo(y) >= 0)
{
i = m;
h = m - 1;
}
else
{
l = m + 1;
}
}
return i;
}
public static int GT<G, E>(G[] a, E y, IComparer<G, E> c, int l, int h)
{
var i = h + 1;
while (l <= h)
{
var m = (int) (uint) (l + h) >> 1;
var x = a[m];
if (c.Compare(x, y) > 0)
{
i = m;
h = m - 1;
}
else
{
l = m + 1;
}
}
return i;
}
public static int GT<G>(G[] a, G y, int l, int h) where G : IComparable<G>
{
var i = h + 1;
while (l <= h)
{
var m = (int) (uint) (l + h) >> 1;
var x = a[m];
if (x.CompareTo(y) > 0)
{
i = m;
h = m - 1;
}
else
{
l = m + 1;
}
}
return i;
}
public static int LT<G, E>(G[] a, E y, IComparer<G, E> c, int l, int h)
{
var i = l - 1;
while (l <= h)
{
var m = (int) (uint) (l + h) >> 1;
var x = a[m];
if (c.Compare(x, y) < 0)
{
i = m;
l = m + 1;
}
else
{
h = m - 1;
}
}
return i;
}
public static int LT<G>(G[] a, G y, int l, int h) where G : IComparable<G>
{
var i = l - 1;
while (l <= h)
{
var m = (int) (uint) (l + h) >> 1;
var x = a[m];
if (x.CompareTo(y) < 0)
{
i = m;
l = m + 1;
}
else
{
h = m - 1;
}
}
return i;
}
public static int LE<G, E>(G[] a, E y, IComparer<G, E> c, int l, int h)
{
var i = l - 1;
while (l <= h)
{
var m = (int) (uint) (l + h) >> 1;
var x = a[m];
if (c.Compare(x, y) <= 0)
{
i = m;
l = m + 1;
}
else
{
h = m - 1;
}
}
return i;
}
public static int LE<G>(G[] a, G y, int l, int h) where G : IComparable<G>
{
var i = l - 1;
while (l <= h)
{
var m = (int) (uint) (l + h) >> 1;
var x = a[m];
if (x.CompareTo(y) <= 0)
{
i = m;
l = m + 1;
}
else
{
h = m - 1;
}
}
return i;
}
public static int EQ<G, E>(G[] a, E y, IComparer<G, E> c, int l, int h)
{
while (l <= h)
{
var m = (int) (uint) (l + h) >> 1;
var x = a[m];
var p = c.Compare(x, y);
if (p == 0)
{
return m;
}
if (p <= 0)
{
l = m + 1;
}
else
{
h = m - 1;
}
}
return -1;
}
public static int EQ<G>(G[] a, G y, int l, int h) where G : IComparable<G>
{
while (l <= h)
{
var m = (int) (uint) (l + h) >> 1;
var x = a[m];
var p = x.CompareTo(y);
if (p == 0)
{
return m;
}
if (p <= 0)
{
l = m + 1;
}
else
{
h = m - 1;
}
}
return -1;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ebc1111a29cd4d6c89f5458aa07da178
timeCreated: 1519710584

View File

@@ -0,0 +1,179 @@
/*
MIT License
Copyright (c) 2018 Yoshihiro Shindo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace DA_Assets.SVGMeshUnity.Internals.Cdt2d
{
public class DelaunayRefine
{
public WorkBufferPool WorkBufferPool;
//Assume edges are sorted lexicographically
public void RefineTriangles(Triangles triangles)
{
var stack = WorkBufferPool.Get<Int2>();
var points = triangles.Vertices;
var numPoints = points.Count;
var stars = triangles.Stars;
for (var a = 0; a < numPoints; ++a)
{
var star = stars[a];
var starData = star.Data;
var sl = star.UsedSize;
for (var j = 0; j < sl; ++j)
{
var s = starData[j];
var b = s.y;
//If order is not consistent, then skip edge
if (b < a)
{
continue;
}
//Check if edge is constrained
if (triangles.IsConstraint(a, b))
{
continue;
}
//Find opposite edge
var x = s.x;
var y = -1;
for (var k = 0; k < sl; ++k)
{
if (starData[k].x == b)
{
y = starData[k].y;
break;
}
}
//If this is a boundary edge, don't flip it
if (y < 0)
{
continue;
}
//If edge is in circle, flip it
if (Robust.InSphere(points[a], points[b], points[x], points[y]) < 0f)
{
var v = new Int2(a, b);
stack.Push(ref v);
}
}
}
while (stack.UsedSize > 0)
{
var v = stack.Pop();
var a = v.x;
var b = v.y;
//Find opposite pairs
var x = -1;
var y = -1;
var star = stars[a];
var starData = star.Data;
var sl = star.UsedSize;
for (var i = 0; i < sl; ++i)
{
var s = starData[i].x;
var t = starData[i].y;
if (s == b)
{
y = t;
}
else if (t == b)
{
x = s;
}
}
//If x/y are both valid then skip edge
if (x < 0 || y < 0)
{
continue;
}
//If edge is now delaunay, then don't flip it
if (Robust.InSphere(points[a], points[b], points[x], points[y]) >= 0f)
{
continue;
}
//Flip the edge
triangles.Flip(a, b);
//Test flipping neighboring edges
TestFlip(points, triangles, stack, x, a, y);
TestFlip(points, triangles, stack, a, y, x);
TestFlip(points, triangles, stack, y, b, x);
TestFlip(points, triangles, stack, b, x, y);
}
WorkBufferPool.Release(ref stack);
}
private void TestFlip(List<Vector3> points, Triangles triangles, WorkBuffer<Int2> stack, int a, int b, int x)
{
var y = triangles.Opposite(a, b);
//Test boundary edge
if (y < 0)
{
return;
}
//Swap edge if order flipped
if (b < a)
{
var tmp = a;
a = b;
b = tmp;
tmp = x;
x = y;
y = tmp;
}
//Test if edge is constrained
if (triangles.IsConstraint(a, b))
{
return;
}
//Test if edge is delaunay
if (Robust.InSphere(points[a], points[b], points[x], points[y]) < 0f)
{
var v = new Int2(a, b);
stack.Push(ref v);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: daf4535a11864f7e9737bf2657ad86e1
timeCreated: 1519795855

View File

@@ -0,0 +1,362 @@
/*
MIT License
Copyright (c) 2018 Yoshihiro Shindo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace DA_Assets.SVGMeshUnity.Internals.Cdt2d
{
public class Filter
{
public int Target;
public bool Infinity;
public WorkBufferPool WorkBufferPool;
public void Do(Triangles triangles, List<int> result)
{
using (var index = IndexCells(triangles))
{
var cellN = index.Cells.UsedSize;
if (result.Capacity < cellN * 3)
{
result.Capacity = cellN * 3;
}
result.Clear();
if (Target == 0)
{
if (Infinity)
{
FillTriangles(index.Cells, result);
FillTriangles(index.Boundary, result);
return;
}
else
{
FillTriangles(index.Cells, result);
return;
}
}
var side = 1;
var active = index.Active;
var next = index.Next;
var flags = index.Flags;
var flagsData = flags.Data;
var cells = index.Cells;
var constraint = index.Constraint;
var constraintData = constraint.Data;
var neighbor = index.Neighbor;
var neighborData = neighbor.Data;
while (active.UsedSize > 0 || next.UsedSize > 0)
{
while (active.UsedSize > 0)
{
var t = active.Pop();
if (flagsData[t] == -side)
{
continue;
}
flagsData[t] = side;
for (var j = 0; j < 3; ++j)
{
var f = neighborData[3 * t + j];
if (f >= 0 && flagsData[f] == 0)
{
if (constraintData[3 * t + j])
{
next.Push(ref f);
}
else
{
active.Push(ref f);
flagsData[f] = side;
}
}
}
}
//Swap arrays and loop
var tmp = next;
next = active;
active = tmp;
next.Clear();
side = -side;
}
FilterCells(cells, flags);
FillTriangles(cells, result);
if (Infinity)
{
FillTriangles(index.Boundary, result);
}
}
}
private class FaceIndex : IDisposable
{
public FaceIndex(WorkBufferPool pool)
{
WorkBufferPool = pool;
pool.Get(ref Cells);
pool.Get(ref Neighbor);
pool.Get(ref Constraint);
pool.Get(ref Flags);
pool.Get(ref Active);
pool.Get(ref Next);
pool.Get(ref Boundary);
}
public WorkBuffer<Int3> Cells;
public WorkBuffer<int> Neighbor;
public WorkBuffer<bool> Constraint;
public WorkBuffer<int> Flags;
public WorkBuffer<int> Active;
public WorkBuffer<int> Next;
public WorkBuffer<Int3> Boundary;
private WorkBufferPool WorkBufferPool;
private bool Disposed = false;
public void Dispose()
{
Dispose(true);
}
private void Dispose(bool disposing)
{
if (Disposed)
{
return;
}
if (disposing)
{
WorkBufferPool.Release(ref Boundary);
WorkBufferPool.Release(ref Next);
WorkBufferPool.Release(ref Active);
WorkBufferPool.Release(ref Flags);
WorkBufferPool.Release(ref Constraint);
WorkBufferPool.Release(ref Neighbor);
WorkBufferPool.Release(ref Cells);
}
Disposed = true;
}
public void Dump()
{
Debug.LogFormat("Cells:\n{0}\n", Dump(Cells));
Debug.LogFormat("Neighbor:\n{0}\n", Dump(Neighbor));
Debug.LogFormat("Flags:\n{0}\n", Dump(Flags));
Debug.LogFormat("Constraint:\n{0}\n", Dump(Constraint));
Debug.LogFormat("Active:\n{0}\n", Dump(Active));
Debug.LogFormat("Next:\n{0}\n", Dump(Next));
Debug.LogFormat("Boundary:\n{0}\n", Dump(Boundary));
}
private string Dump<T>(WorkBuffer<T> buf)
{
return buf.Data.Take(buf.UsedSize).Aggregate("", (_, s) => _ + " " + s.ToString() + ",\n");
}
}
private FaceIndex IndexCells(Triangles triangles)
{
var zero = 0;
var fals = false;
var index = new FaceIndex(WorkBufferPool);
triangles.Fill(index.Cells);
//First get cells and canonicalize
var cells = index.Cells;
var nc = cells.UsedSize;
var cellsData = cells.Data;
for (var i = 0; i < nc; ++i)
{
var c = cellsData[i];
var x = c.x;
var y = c.y;
var z = c.z;
if (y < z)
{
if (y < x)
{
c.x = y;
c.y = z;
c.z = x;
cellsData[i] = c;
}
}
else if (z < x)
{
c.x = z;
c.y = x;
c.z = y;
cellsData[i] = c;
}
}
WorkBuffer<Int3>.Sort(cells);
//Initialize flag array
var flags = index.Flags;
flags.Fill(ref zero, nc);
//Build neighbor index, initialize queues
var active = index.Active;
var next = index.Next;
var neighbor = index.Neighbor;
var constraint = index.Constraint;
var boundary = index.Boundary;
neighbor.Fill(ref zero, nc * 3);
constraint.Fill(ref fals, nc * 3);
var flagsData = flags.Data;
var neighborData = neighbor.Data;
var constraintData = constraint.Data;
for (var i = 0; i < nc; ++i)
{
var c = cellsData[i];
for (var j = 0; j < 3; ++j)
{
var x = 0;
var y = 0;
switch (j)
{
case 0:
x = c.x;
y = c.y;
break;
case 1:
x = c.y;
y = c.z;
break;
case 2:
x = c.z;
y = c.x;
break;
}
var a = neighborData[3 * i + j] = Locate(cells, y, x, triangles.Opposite(y, x));
var b = constraintData[3 * i + j] = triangles.IsConstraint(x, y);
if (a < 0)
{
if (b)
{
next.Push(ref i);
}
else
{
active.Push(ref i);
flagsData[i] = 1;
}
if (Infinity)
{
var v = new Int3(y, x, -1);
boundary.Push(ref v);
}
}
}
}
return index;
}
private int Locate(WorkBuffer<Int3> cells, int a, int b, int c)
{
var x = a;
var y = b;
var z = c;
if (b < c)
{
if (b < a)
{
x = b;
y = c;
z = a;
}
}
else if (c < a)
{
x = c;
y = a;
z = b;
}
if (x < 0)
{
return -1;
}
return BinarySearch.EQ(cells.Data, new Int3(x, y, z), 0, cells.UsedSize - 1);
}
private void FilterCells(WorkBuffer<Int3> cells, WorkBuffer<int> flags)
{
var ptr = 0;
var n = cells.UsedSize;
var cellsData = cells.Data;
var flagsData = flags.Data;
for (var i = 0; i < n; ++i) {
if(flagsData[i] == Target)
{
cellsData[ptr++] = cellsData[i];
}
}
cells.RemoveLast(n - ptr);
}
private void FillTriangles(WorkBuffer<Int3> from, List<int> to)
{
var n = from.UsedSize;
if (to.Capacity < n * 3)
{
to.Capacity = n * 3;
}
var data = from.Data;
for (var i = 0; i < n; ++i)
{
var v = data[i];
to.Add(v.x);
to.Add(v.y);
to.Add(v.z);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1384c72d4a744c9db5fbd24870a9c0e5
timeCreated: 1519830352

View File

@@ -0,0 +1,405 @@
/*
MIT License
Copyright (c) 2018 Yoshihiro Shindo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace DA_Assets.SVGMeshUnity.Internals.Cdt2d
{
public class MonotoneTriangulation
{
private static readonly bool Verbose = false;
public WorkBufferPool WorkBufferPool;
private enum EventType
{
Point = 0,
End = 1,
Start = 2,
}
//An event in the sweep line procedure
private class Event : IComparable<Event>
{
public Vector2 A;
public Vector2 B;
public EventType Type;
public int Index;
//This is used to compare events for the sweep line procedure
// Points are:
// 1. sorted lexicographically
// 2. sorted by type (point < end < start)
// 3. segments sorted by winding order
// 4. sorted by index
public int CompareTo(Event b)
{
var d = 0;
d = Sign(A.x - b.A.x);
if (d != 0) return d;
d = Sign(A.y - b.A.y);
if (d != 0) return d;
d = Type - b.Type;
if (d != 0) return d;
if (Type != EventType.Point)
{
d = Sign(Robust.Orientation(A, B, b.B));
if (d != 0) return d;
}
return Index - b.Index;
}
}
//A partial convex hull fragment, made of two unimonotone polygons
private class PartialHull
{
public Vector2 A;
public Vector2 B;
public int Index;
public WorkBuffer<int> LowerIds = new WorkBuffer<int>(8);
public WorkBuffer<int> UpperIds = new WorkBuffer<int>(8);
}
public void BuildTriangles(MeshData data)
{
var numPoints = data.Vertices.Count;
var numEdges = data.Edges.Count;
data.Triangles.Capacity = numPoints * 3;
var events = WorkBufferPool.Get<Event>();
if (events.NewForClass == null)
{
events.NewForClass = () => new Event();
}
//Create point events
for (var i = 0; i < numPoints; ++i)
{
var e = events.Push();
e.A = data.Vertices[i];
e.B = Vector2.zero;
e.Type = EventType.Point;
e.Index = i;
}
//Create edge events
for(var i=0; i<numEdges; ++i)
{
var edge = data.Edges[i];
var a = data.Vertices[edge.x];
var b = data.Vertices[edge.y];
if(a.x < b.x)
{
{
var e = events.Push();
e.A = a;
e.B = b;
e.Type = EventType.Start;
e.Index = i;
}
{
var e = events.Push();
e.A = b;
e.B = a;
e.Type = EventType.End;
e.Index = i;
}
}
else if(a.x > b.x)
{
{
var e = events.Push();
e.A = b;
e.B = a;
e.Type = EventType.Start;
e.Index = i;
}
{
var e = events.Push();
e.A = a;
e.B = b;
e.Type = EventType.End;
e.Index = i;
}
}
}
//Sort events
WorkBuffer<Event>.Sort(events);
if (Verbose)
{
DumpEvents(events);
}
//Initialize hull
var minX = events.Data[0].A.x - 1f;
var hulls = WorkBufferPool.Get<PartialHull>();
if (hulls.NewForClass == null)
{
hulls.NewForClass = () => new PartialHull();
}
var h = hulls.Push();
h.A = new Vector2(minX, 1f);
h.B = new Vector2(minX, 0f);
h.Index = -1;
h.LowerIds.Clear();
h.UpperIds.Clear();
//Process events in order
var numEvents = events.UsedSize;
for (var i = 0; i < numEvents; ++i)
{
var e = events.Data[i];
if (Verbose)
{
Debug.Log("");
Debug.Log(i);
DumpEvent(e);
}
switch (e.Type)
{
case EventType.Point:
AddPoint(data.Triangles, hulls, data.Vertices, e.A, e.Index);
break;
case EventType.Start:
SplitHulls(hulls, e);
break;
case EventType.End:
MergeHulls(hulls, e);
break;
}
if (Verbose)
{
Debug.Log("");
}
}
WorkBufferPool.Release(ref hulls);
WorkBufferPool.Release(ref events);
}
private static int Sign(float n)
{
if (n < 0f)
{
return -1;
}
if (n > 0f)
{
return 1;
}
return 0;
}
private void AddPoint(List<int> cells, WorkBuffer<PartialHull> hulls, List<Vector3> points, Vector2 p, int idx)
{
var lo = BinarySearch.LT(hulls.Data, p, TestPoint.Default, 0, hulls.UsedSize - 1);
var hi = BinarySearch.GT(hulls.Data, p, TestPoint.Default, 0, hulls.UsedSize - 1);
for (var i = lo; i < hi; ++i)
{
var hull = hulls.Data[i];
//Insert p into lower hull
{
var lowerIds = hull.LowerIds;
var m = lowerIds.UsedSize;
var lowerIdsData = lowerIds.Data;
while (m > 1 && Robust.Orientation(points[lowerIdsData[m - 2]], points[lowerIdsData[m - 1]], p) > 0f)
{
cells.Add(lowerIdsData[m - 1]);
cells.Add(lowerIdsData[m - 2]);
cells.Add(idx);
m -= 1;
}
if (m < lowerIds.UsedSize)
{
lowerIds.RemoveLast(lowerIds.UsedSize - m);
}
lowerIds.Push(ref idx);
}
//Insert p into upper hull
{
var upperIds = hull.UpperIds;
var m = upperIds.UsedSize;
var upperIdsData = upperIds.Data;
while (m > 1 && Robust.Orientation(points[upperIdsData[m - 2]], points[upperIdsData[m - 1]], p) < 0f)
{
cells.Add(upperIdsData[m - 2]);
cells.Add(upperIdsData[m - 1]);
cells.Add(idx);
m -= 1;
}
if (m < upperIds.UsedSize)
{
upperIds.RemoveLast(upperIds.UsedSize - m);
}
upperIds.Push(ref idx);
}
}
if (Verbose)
{
Debug.Log("Add");
DumpHulls(hulls);
hulls.Dump();
}
}
private void SplitHulls(WorkBuffer<PartialHull> hulls, Event e)
{
var splitIdx = BinarySearch.LE(hulls.Data, e, FindSplit.Default, 0, hulls.UsedSize - 1);
var hull = hulls.Data[splitIdx];
var upperIds = hull.UpperIds;
var x = upperIds.Data[upperIds.UsedSize - 1];
hull.UpperIds = new WorkBuffer<int>(8);
hull.UpperIds.Push(ref x);
var h = hulls.Insert(splitIdx + 1);
h.A = e.A;
h.B = e.B;
h.Index = e.Index;
h.LowerIds.Clear();
h.LowerIds.Push(ref x);
h.UpperIds = upperIds;
if (Verbose)
{
Debug.Log("Split: " + splitIdx);
DumpHulls(hulls);
hulls.Dump();
}
}
private void MergeHulls(WorkBuffer<PartialHull> hulls, Event e)
{
//Swap pointers for merge search
var tmp = e.A;
e.A = e.B;
e.B = tmp;
var mergeIdx = BinarySearch.EQ(hulls.Data, e, FindSplit.Default, 0, hulls.UsedSize - 1);
var upper = hulls.Data[mergeIdx];
var lower = hulls.Data[mergeIdx - 1];
lower.UpperIds = upper.UpperIds;
hulls.RemoveAt(mergeIdx);
if (Verbose)
{
Debug.Log("Merge: " + mergeIdx);
DumpHulls(hulls);
hulls.Dump();
}
}
private class TestPoint : BinarySearch.IComparer<PartialHull, Vector2>
{
public static readonly TestPoint Default = new TestPoint();
public int Compare(PartialHull hull, Vector2 p)
{
return Sign(Robust.Orientation(hull.A, hull.B, p));
}
}
private class FindSplit : BinarySearch.IComparer<PartialHull, Event>
{
public static readonly FindSplit Default = new FindSplit();
public int Compare(PartialHull hull, Event edge)
{
var d = 0;
if (hull.A.x < edge.A.x)
{
d = Sign(Robust.Orientation(hull.A, hull.B, edge.A));
} else
{
d = Sign(Robust.Orientation(edge.B, edge.A, hull.A));
}
if (d != 0) return d;
if (edge.B.x < hull.B.x)
{
d = Sign(Robust.Orientation(hull.A, hull.B, edge.B));
} else
{
d = Sign(Robust.Orientation(edge.B, edge.A, hull.B));
}
if (d != 0) return d;
return hull.Index - edge.Index;
}
}
#region Debug
private void DumpEvent(Event _)
{
Debug.Log(string.Format("{{ a: {0}, b: {1}, type: {2}, idx: {3} }}", _.A, _.B, _.Type, _.Index));
}
private void DumpEvents(WorkBuffer<Event> events)
{
Debug.Log(events.Data.Take(events.UsedSize)
.Select(_ => string.Format("{{ a: {0}, b: {1}, type: {2}, idx: {3} }}", _.A, _.B, _.Type, _.Index))
.Aggregate("", (_, s) => _ + s + "\n"));
}
private void DumpHulls(WorkBuffer<PartialHull> hulls)
{
Debug.Log(hulls.Data.Take(hulls.UsedSize)
.Select(_ => string.Format("{{ a: {0}, b: {1}, idx: {2}, lowerIds: [ {3} ], upperIds: [ {4} ] }}", _.A, _.B, _.Index, ToString(_.LowerIds), ToString(_.UpperIds)))
.Aggregate("", (_, s) => _ + s + "\n"));
}
private string ToString(WorkBuffer<int> list)
{
return string.Join(", ", list.Data.Take(list.UsedSize).Select(_ => _.ToString()).ToArray());
}
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f3f866907d0c43a086ba61429b3d2b8a
timeCreated: 1519699803

View File

@@ -0,0 +1,930 @@
/*
The MIT License (MIT)
Copyright (c) 2013 Mikola Lysenko
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/*
The MIT License (MIT)
Copyright (c) 2014 Mikola Lysenko
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
using UnityEngine;
namespace DA_Assets.SVGMeshUnity.Internals.Cdt2d
{
public static class Robust
{
// https://github.com/mikolalysenko/robust-orientation
// https://github.com/mikolalysenko/robust-in-sphere
// https://github.com/mikolalysenko/robust-sum
// https://github.com/mikolalysenko/robust-subtract
// https://github.com/mikolalysenko/robust-scale
// https://github.com/mikolalysenko/two-product
// https://github.com/mikolalysenko/two-sum
private static readonly float Epsilon = 1.1102230246251565e-16f;
private static readonly float Errbound3 = (3.0f + 16.0f * Epsilon) * Epsilon;
private static readonly float Splitter = +(Mathf.Pow(2f, 27f) + 1.0f);
private static float[][] BufferPool = new float[32][];
private static int BufferPoolSize = 0;
private static float[] GetTemporaryBuffer()
{
if (BufferPoolSize > 0)
{
return BufferPool[--BufferPoolSize];
}
return new float[16];
}
private static void ReleaseTemporaryBuffer(ref float[] buf)
{
if (BufferPool.Length == BufferPoolSize)
{
var newBufferPool = new float[BufferPool.Length + 32][];
BufferPool.CopyTo(newBufferPool, 0);
BufferPool = newBufferPool;
}
BufferPool[BufferPoolSize++] = buf;
buf = null;
}
public static float Orientation(Vector2 a, Vector2 b, Vector2 c)
{
var l = (a.y - c.y) * (b.x - c.x);
var r = (a.x - c.x) * (b.y - c.y);
var det = l - r;
var s = 0f;
if (l > 0)
{
if (r <= 0)
{
return det;
}
else
{
s = l + r;
}
}
else if (l < 0)
{
if (r >= 0)
{
return det;
}
else
{
s = -(l + r);
}
}
else
{
return det;
}
var tol = Errbound3 * s;
if (det >= tol || det <= -tol)
{
return det;
}
var m0 = a;
var m1 = b;
var m2 = c;
var sL = GetTemporaryBuffer();
var sR = GetTemporaryBuffer();
var p = GetTemporaryBuffer();
var n = GetTemporaryBuffer();
var d = GetTemporaryBuffer();
var pN = 0;
var nN = 0;
var dN = 0;
var pL = GetTemporaryBuffer();
var pR = GetTemporaryBuffer();
var pLN = 0;
var pRN = 0;
TwoProd( m1.y, m2.x, sL);
TwoProd(-m2.y, m1.x, sR);
Sum(sL, 2, sR, 2, pL, out pLN);
TwoProd( m0.y, m1.x, sL);
TwoProd(-m1.y, m0.x, sR);
Sum(sL, 2, sR, 2, pR, out pRN);
Sum(pL, pLN, pR, pRN, p, out pN);
ReleaseTemporaryBuffer(ref pL);
ReleaseTemporaryBuffer(ref pR);
TwoProd( m0.y, m2.x, sL);
TwoProd(-m2.y, m0.x, sR);
Sum(sL, 2, sR, 2, n, out nN);
ReleaseTemporaryBuffer(ref sL);
ReleaseTemporaryBuffer(ref sR);
Sub(p, pN, n, nN, d, out dN);
var result = d[dN - 1];
ReleaseTemporaryBuffer(ref p);
ReleaseTemporaryBuffer(ref n);
ReleaseTemporaryBuffer(ref d);
return result;
}
public static float InSphere(Vector2 m0, Vector2 m1, Vector2 m2, Vector2 m3)
{
var w = GetTemporaryBuffer();
var wL = GetTemporaryBuffer();
var wR = GetTemporaryBuffer();
var wN = 0;
var w0m1 = GetTemporaryBuffer();
var w0m2 = GetTemporaryBuffer();
var w0m3 = GetTemporaryBuffer();
var w1m0 = GetTemporaryBuffer();
var w1m2 = GetTemporaryBuffer();
var w1m3 = GetTemporaryBuffer();
var w2m0 = GetTemporaryBuffer();
var w2m1 = GetTemporaryBuffer();
var w2m3 = GetTemporaryBuffer();
var w3m0 = GetTemporaryBuffer();
var w3m1 = GetTemporaryBuffer();
var w3m2 = GetTemporaryBuffer();
var w0m1N = 0;
var w0m2N = 0;
var w0m3N = 0;
var w1m0N = 0;
var w1m2N = 0;
var w1m3N = 0;
var w2m0N = 0;
var w2m1N = 0;
var w2m3N = 0;
var w3m0N = 0;
var w3m1N = 0;
var w3m2N = 0;
TwoProd(m0[0], m0[0], wL);
TwoProd(m0[1], m0[1], wR);
Sum(wL, 2, wR, 2, w, out wN);
Scale(w, wN, m1[0], w0m1, out w0m1N);
Scale(w, wN, m2[0], w0m2, out w0m2N);
Scale(w, wN, m3[0], w0m3, out w0m3N);
TwoProd(m1[0], m1[0], wL);
TwoProd(m1[1], m1[1], wR);
Sum(wL, 2, wR, 2, w, out wN);
Scale(w, wN, m0[0], w1m0, out w1m0N);
Scale(w, wN, m2[0], w1m2, out w1m2N);
Scale(w, wN, m3[0], w1m3, out w1m3N);
TwoProd(m2[0], m2[0], wL);
TwoProd(m2[1], m2[1], wR);
Sum(wL, 2, wR, 2, w, out wN);
Scale(w, wN, m0[0], w2m0, out w2m0N);
Scale(w, wN, m1[0], w2m1, out w2m1N);
Scale(w, wN, m3[0], w2m3, out w2m3N);
TwoProd(m3[0], m3[0], wL);
TwoProd(m3[1], m3[1], wR);
Sum(wL, 2, wR, 2, w, out wN);
Scale(w, wN, m0[0], w3m0, out w3m0N);
Scale(w, wN, m1[0], w3m1, out w3m1N);
Scale(w, wN, m2[0], w3m2, out w3m2N);
ReleaseTemporaryBuffer(ref wL);
ReleaseTemporaryBuffer(ref wR);
ReleaseTemporaryBuffer(ref w);
var p = GetTemporaryBuffer();
var n = GetTemporaryBuffer();
var d = GetTemporaryBuffer();
var pN = 0;
var nN = 0;
var dN = 0;
var pL = GetTemporaryBuffer();
var pR = GetTemporaryBuffer();
var pLN = 0;
var pRN = 0;
var pLLL = GetTemporaryBuffer();
var pLL = GetTemporaryBuffer();
var pLRLL = GetTemporaryBuffer();
var pLRL = GetTemporaryBuffer();
var pLRRL = GetTemporaryBuffer();
var pLRR = GetTemporaryBuffer();
var pLR = GetTemporaryBuffer();
var pLLLN = 0;
var pLLN = 0;
var pLRLLN = 0;
var pLRLN = 0;
var pLRRLN = 0;
var pLRRN = 0;
var pLRN = 0;
Sub(w3m2, w3m2N, w2m3, w2m3N, pLLL, out pLLLN);
Scale(pLLL, pLLLN, m1[1], pLL, out pLLN);
Sub(w3m1, w3m1N, w1m3, w1m3N, pLRLL, out pLRLLN);
Scale(pLRLL, pLRLLN, -m2[1], pLRL, out pLRLN);
Sub(w2m1, w2m1N, w1m2, w1m2N, pLRRL, out pLRRLN);
Scale(pLRRL, pLRRLN, m3[1], pLRR, out pLRRN);
Sum(pLRL, pLRLN, pLRR, pLRRN, pLR, out pLRN);
Sum(pLL, pLLN, pLR, pLRN, pL, out pLN);
ReleaseTemporaryBuffer(ref pLLL);
ReleaseTemporaryBuffer(ref pLL);
ReleaseTemporaryBuffer(ref pLRLL);
ReleaseTemporaryBuffer(ref pLRL);
ReleaseTemporaryBuffer(ref pLRRL);
ReleaseTemporaryBuffer(ref pLRR);
ReleaseTemporaryBuffer(ref pLR);
var pRLL = GetTemporaryBuffer();
var pRL = GetTemporaryBuffer();
var pRRLL = GetTemporaryBuffer();
var pRRL = GetTemporaryBuffer();
var pRRRL = GetTemporaryBuffer();
var pRRR = GetTemporaryBuffer();
var pRR = GetTemporaryBuffer();
var pRLLN = 0;
var pRLN = 0;
var pRRLLN = 0;
var pRRLN = 0;
var pRRRLN = 0;
var pRRRN = 0;
var pRRN = 0;
Sub(w3m1, w3m1N, w1m3, w1m3N, pRLL, out pRLLN);
Scale(pRLL, pRLLN, m0[1], pRL, out pRLN);
Sub(w3m0, w3m0N, w0m3, w0m3N, pRRLL, out pRRLLN);
Scale(pRRLL, pRRLLN, -m1[1], pRRL, out pRRLN);
Sub(w1m0, w1m0N, w0m1, w0m1N, pRRRL, out pRRRLN);
Scale(pRRRL, pRRRLN, m3[1], pRRR, out pRRRN);
Sum(pRRL, pRRLN, pRRR, pRRRN, pRR, out pRRN);
Sum(pRL, pRLN, pRR, pRRN, pR, out pRN);
ReleaseTemporaryBuffer(ref pRLL);
ReleaseTemporaryBuffer(ref pRL);
ReleaseTemporaryBuffer(ref pRRLL);
ReleaseTemporaryBuffer(ref pRRL);
ReleaseTemporaryBuffer(ref pRRRL);
ReleaseTemporaryBuffer(ref pRRR);
ReleaseTemporaryBuffer(ref pRR);
Sum(pL, pLN, pR, pRN, p, out pN);
ReleaseTemporaryBuffer(ref pL);
ReleaseTemporaryBuffer(ref pR);
var nL = GetTemporaryBuffer();
var nR = GetTemporaryBuffer();
var nLN = 0;
var nRN = 0;
var nLLL = GetTemporaryBuffer();
var nLL = GetTemporaryBuffer();
var nLRLL = GetTemporaryBuffer();
var nLRL = GetTemporaryBuffer();
var nLRRL = GetTemporaryBuffer();
var nLRR = GetTemporaryBuffer();
var nLR = GetTemporaryBuffer();
var nLLLN = 0;
var nLLN = 0;
var nLRLLN = 0;
var nLRLN = 0;
var nLRRLN = 0;
var nLRRN = 0;
var nLRN = 0;
Sub(w3m2, w3m2N, w2m3, w2m3N, nLLL, out nLLLN);
Scale(nLLL, nLLLN, m0[1], nLL, out nLLN);
Sub(w3m0, w3m0N, w0m3, w0m3N, nLRLL, out nLRLLN);
Scale(nLRLL, nLRLLN, -m2[1], nLRL, out nLRLN);
Sub(w2m0, w2m0N, w0m2, w0m2N, nLRRL, out nLRRLN);
Scale(nLRRL, nLRRLN, m3[1], nLRR, out nLRRN);
Sum(nLRL, nLRLN, nLRR, nLRRN, nLR, out nLRN);
Sum(nLL, nLLN, nLR, nLRN, nL, out nLN);
ReleaseTemporaryBuffer(ref nLLL);
ReleaseTemporaryBuffer(ref nLL);
ReleaseTemporaryBuffer(ref nLRLL);
ReleaseTemporaryBuffer(ref nLRL);
ReleaseTemporaryBuffer(ref nLRRL);
ReleaseTemporaryBuffer(ref nLRR);
ReleaseTemporaryBuffer(ref nLR);
var nRLL = GetTemporaryBuffer();
var nRL = GetTemporaryBuffer();
var nRRLL = GetTemporaryBuffer();
var nRRL = GetTemporaryBuffer();
var nRRRL = GetTemporaryBuffer();
var nRRR = GetTemporaryBuffer();
var nRR = GetTemporaryBuffer();
var nRLLN = 0;
var nRLN = 0;
var nRRLLN = 0;
var nRRLN = 0;
var nRRRLN = 0;
var nRRRN = 0;
var nRRN = 0;
Sub(w2m1, w2m1N, w1m2, w1m2N, nRLL, out nRLLN);
Scale(nRLL, nRLLN, m0[1], nRL, out nRLN);
Sub(w2m0, w2m0N, w0m2, w0m2N, nRRLL, out nRRLLN);
Scale(nRRLL, nRRLLN, -m1[1], nRRL, out nRRLN);
Sub(w1m0, w1m0N, w0m1, w0m1N, nRRRL, out nRRRLN);
Scale(nRRRL, nRRRLN, m2[1], nRRR, out nRRRN);
Sum(nRRL, nRRLN, nRRR, nRRRN, nRR, out nRRN);
Sum(nRL, nRLN, nRR, nRRN, nR, out nRN);
ReleaseTemporaryBuffer(ref nRLL);
ReleaseTemporaryBuffer(ref nRL);
ReleaseTemporaryBuffer(ref nRRLL);
ReleaseTemporaryBuffer(ref nRRL);
ReleaseTemporaryBuffer(ref nRRRL);
ReleaseTemporaryBuffer(ref nRRR);
ReleaseTemporaryBuffer(ref nRR);
Sum(nL, nLN, nR, nRN, n, out nN);
ReleaseTemporaryBuffer(ref nL);
ReleaseTemporaryBuffer(ref nR);
ReleaseTemporaryBuffer(ref w0m1);
ReleaseTemporaryBuffer(ref w0m2);
ReleaseTemporaryBuffer(ref w0m3);
ReleaseTemporaryBuffer(ref w1m0);
ReleaseTemporaryBuffer(ref w1m2);
ReleaseTemporaryBuffer(ref w1m3);
ReleaseTemporaryBuffer(ref w2m0);
ReleaseTemporaryBuffer(ref w2m1);
ReleaseTemporaryBuffer(ref w2m3);
ReleaseTemporaryBuffer(ref w3m0);
ReleaseTemporaryBuffer(ref w3m1);
ReleaseTemporaryBuffer(ref w3m2);
Sub(p, pN, n, nN, d, out dN);
var result = d[dN - 1];
ReleaseTemporaryBuffer(ref p);
ReleaseTemporaryBuffer(ref n);
ReleaseTemporaryBuffer(ref d);
return result;
}
private static void TwoProd(float a, float b, float[] result)
{
var x = a * b;
var c = Splitter * a;
var abig = c - a;
var ahi = c - abig;
var alo = a - ahi;
var d = Splitter * b;
var bbig = d - b;
var bhi = d - bbig;
var blo = b - bhi;
var err1 = x - (ahi * bhi);
var err2 = err1 - (alo * bhi);
var err3 = err2 - (ahi * blo);
var y = alo * blo - err3;
result[0] = y;
result[1] = x;
}
private static void TwoSum(float a, float b, float[] result)
{
var x = a + b;
var bv = x - a;
var av = x - bv;
var br = b - bv;
var ar = a - av;
result[0] = ar + br;
result[1] = x;
}
private static void Sum(float[] e, int eN, float[] f, int fN, float[] result, out int resultN)
{
if(eN == 1 && fN == 1)
{
ScalarScalar(e[0], f[0], result, out resultN);
return;
}
resultN = 0;
var eptr = 0;
var fptr = 0;
var ei = e[eptr];
var ea = Mathf.Abs(ei);
var fi = f[fptr];
var fa = Mathf.Abs(fi);
var a = 0f;
var b = 0f;
if (ea < fa)
{
b = ei;
eptr += 1;
if (eptr < eN)
{
ei = e[eptr];
ea = Mathf.Abs(ei);
}
}
else
{
b = fi;
fptr += 1;
if (fptr < fN)
{
fi = f[fptr];
fa = Mathf.Abs(fi);
}
}
if ((eptr < eN && ea < fa) || (fptr >= fN))
{
a = ei;
eptr += 1;
if (eptr < eN)
{
ei = e[eptr];
ea = Mathf.Abs(ei);
}
}
else
{
a = fi;
fptr += 1;
if (fptr < fN)
{
fi = f[fptr];
fa = Mathf.Abs(fi);
}
}
var x = a + b;
var bv = x - a;
var y = b - bv;
var q0 = y;
var q1 = x;
var _x = 0f;
var _bv = 0f;
var _av = 0f;
var _br = 0f;
var _ar = 0f;
while (eptr < eN && fptr < fN)
{
if (ea < fa)
{
a = ei;
eptr += 1;
if (eptr < eN)
{
ei = e[eptr];
ea = Mathf.Abs(ei);
}
}
else
{
a = fi;
fptr += 1;
if (fptr < fN)
{
fi = f[fptr];
fa = Mathf.Abs(fi);
}
}
b = q0;
x = a + b;
bv = x - a;
y = b - bv;
if (y != 0f)
{
result[resultN++] = y;
}
_x = q1 + x;
_bv = _x - q1;
_av = _x - _bv;
_br = x - _bv;
_ar = q1 - _av;
q0 = _ar + _br;
q1 = _x;
}
while (eptr < eN)
{
a = ei;
b = q0;
x = a + b;
bv = x - a;
y = b - bv;
if (y != 0f)
{
result[resultN++] = y;
}
_x = q1 + x;
_bv = _x - q1;
_av = _x - _bv;
_br = x - _bv;
_ar = q1 - _av;
q0 = _ar + _br;
q1 = _x;
eptr += 1;
if (eptr < eN)
{
ei = e[eptr];
}
}
while (fptr < fN)
{
a = fi;
b = q0;
x = a + b;
bv = x - a;
y = b - bv;
if (y != 0f)
{
result[resultN++] = y;
}
_x = q1 + x;
_bv = _x - q1;
_av = _x - _bv;
_br = x - _bv;
_ar = q1 - _av;
q0 = _ar + _br;
q1 = _x;
fptr += 1;
if (fptr < fN)
{
fi = f[fptr];
}
}
if (q0 != 0f)
{
result[resultN++] = q0;
}
if (q1 != 0f)
{
result[resultN++] = q1;
}
if (resultN == 0)
{
result[resultN++] = 0f;
}
}
private static void Sub(float[] e, int eN, float[] f, int fN, float[] result, out int resultN)
{
if (eN == 1 && fN == 1)
{
ScalarScalar(e[0], -f[0], result, out resultN);
return;
}
resultN = 0;
var eptr = 0;
var fptr = 0;
var ei = e[eptr];
var ea = Mathf.Abs(ei);
var fi = -f[fptr];
var fa = Mathf.Abs(fi);
var a = 0f;
var b = 0f;
if (ea < fa)
{
b = ei;
eptr += 1;
if (eptr < eN)
{
ei = e[eptr];
ea = Mathf.Abs(ei);
}
}
else
{
b = fi;
fptr += 1;
if (fptr < fN)
{
fi = -f[fptr];
fa = Mathf.Abs(fi);
}
}
if ((eptr < eN && ea < fa) || (fptr >= fN))
{
a = ei;
eptr += 1;
if (eptr < eN)
{
ei = e[eptr];
ea = Mathf.Abs(ei);
}
}
else
{
a = fi;
fptr += 1;
if (fptr < fN)
{
fi = -f[fptr];
fa = Mathf.Abs(fi);
}
}
var x = a + b;
var bv = x - a;
var y = b - bv;
var q0 = y;
var q1 = x;
var _x = 0f;
var _bv = 0f;
var _av = 0f;
var _br = 0f;
var _ar = 0f;
while (eptr < eN && fptr < fN)
{
if (ea < fa)
{
a = ei;
eptr += 1;
if (eptr < eN)
{
ei = e[eptr];
ea = Mathf.Abs(ei);
}
}
else
{
a = fi;
fptr += 1;
if (fptr < fN)
{
fi = -f[fptr];
fa = Mathf.Abs(fi);
}
}
b = q0;
x = a + b;
bv = x - a;
y = b - bv;
if (y != 0f)
{
result[resultN++] = y;
}
_x = q1 + x;
_bv = _x - q1;
_av = _x - _bv;
_br = x - _bv;
_ar = q1 - _av;
q0 = _ar + _br;
q1 = _x;
}
while (eptr < eN)
{
a = ei;
b = q0;
x = a + b;
bv = x - a;
y = b - bv;
if (y != 0f)
{
result[resultN++] = y;
}
_x = q1 + x;
_bv = _x - q1;
_av = _x - _bv;
_br = x - _bv;
_ar = q1 - _av;
q0 = _ar + _br;
q1 = _x;
eptr += 1;
if (eptr < eN)
{
ei = e[eptr];
}
}
while (fptr < fN)
{
a = fi;
b = q0;
x = a + b;
bv = x - a;
y = b - bv;
if (y != 0f)
{
result[resultN++] = y;
}
_x = q1 + x;
_bv = _x - q1;
_av = _x - _bv;
_br = x - _bv;
_ar = q1 - _av;
q0 = _ar + _br;
q1 = _x;
fptr += 1;
if (fptr < fN)
{
fi = -f[fptr];
}
}
if (q0 != 0f)
{
result[resultN++] = q0;
}
if (q1 != 0f)
{
result[resultN++] = q1;
}
if (resultN == 0)
{
result[resultN++] = 0.0f;
}
}
private static void Scale(float[] e, int eN, float scale, float[] result, out int resultN)
{
if (eN == 1)
{
var ts = GetTemporaryBuffer();
TwoProd(e[0], scale, ts);
if (ts[0] != 0f)
{
result[0] = ts[0];
result[1] = ts[1];
resultN = 2;
ReleaseTemporaryBuffer(ref ts);
return;
}
result[0] = ts[1];
resultN = 1;
ReleaseTemporaryBuffer(ref ts);
return;
}
var q = GetTemporaryBuffer();
var t = GetTemporaryBuffer();
q[0] = 0.1f;
q[1] = 0.1f;
t[0] = 0.1f;
t[1] = 0.1f;
resultN = 0;
TwoProd(e[0], scale, q);
if (q[0] != 0f)
{
result[resultN++] = q[0];
}
for (var i = 1; i < eN; ++i)
{
TwoProd(e[i], scale, t);
var pq = q[1];
TwoSum(pq, t[0], q);
if (q[0] != 0f)
{
result[resultN++] = q[0];
}
var a = t[1];
var b = q[1];
var x = a + b;
var bv = x - a;
var y = b - bv;
q[1] = x;
if (y != 0f)
{
result[resultN++] = y;
}
}
if (q[1] != 0f)
{
result[resultN++] = q[1];
}
ReleaseTemporaryBuffer(ref q);
ReleaseTemporaryBuffer(ref t);
if (resultN == 0)
{
result[resultN++] = 0.0f;
}
}
//Easy case: Add two scalars
private static void ScalarScalar(float a, float b, float[] result, out int resultN)
{
var x = a + b;
var bv = x - a;
var av = x - bv;
var br = b - bv;
var ar = a - av;
var y = ar + br;
if (y != 0f)
{
result[0] = y;
result[1] = x;
resultN = 2;
return;
}
result[0] = x;
resultN = 1;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 76852b2115774598947fe907402ed9fd
timeCreated: 1519703003

View File

@@ -0,0 +1,210 @@
/*
MIT License
Copyright (c) 2018 Yoshihiro Shindo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic;
using UnityEngine;
namespace DA_Assets.SVGMeshUnity.Internals.Cdt2d
{
public class Triangles
{
public Triangles(MeshData data)
{
PrivateVertices = data.Vertices;
CreateStars(data.Vertices.Count);
CreateEdges(data.Edges);
CreateTriangles(data.Triangles);
}
public List<Vector3> Vertices
{
get { return PrivateVertices; }
}
public WorkBuffer<Int2>[] Stars
{
get { return PrivateStars; }
}
private List<Vector3> PrivateVertices;
private WorkBuffer<Int2>[] PrivateStars;
private Int2[] Edges;
private void CreateStars(int n)
{
var stars = new WorkBuffer<Int2>[n];
for (var i = 0; i < n; ++i)
{
stars[i] = new WorkBuffer<Int2>(16);
}
PrivateStars = stars;
}
private void CreateEdges(List<Int2> source)
{
var l = source.Count;
var edges = new Int2[l];
for (var i = 0; i < l; ++i)
{
var edge = source[i];
if (edge.y < edge.x)
{
var x = edge.x;
edge.x = edge.y;
edge.y = x;
}
edges[i] = edge;
}
Sort<Int2>.QuickSort(edges, 0, edges.Length - 1);
Edges = edges;
}
private void CreateTriangles(List<int> source)
{
var l = source.Count;
for (var i = 0; i < l; i += 3)
{
AddTriangle(source[i + 0], source[i + 1], source[i + 2]);
}
}
public void AddTriangle(int i, int j, int k)
{
var jk = new Int2(j, k);
var ki = new Int2(k, i);
var ij = new Int2(i, j);
PrivateStars[i].Push(ref jk);
PrivateStars[j].Push(ref ki);
PrivateStars[k].Push(ref ij);
}
public void RemoveTriangle(int i, int j, int k)
{
RemovePair(PrivateStars[i], j, k);
RemovePair(PrivateStars[j], k, i);
RemovePair(PrivateStars[k], i, j);
}
private void RemovePair(WorkBuffer<Int2> list, int j, int k)
{
var n = list.UsedSize;
var data = list.Data;
for (var i = 0; i < n; ++i)
{
var s = data[i];
if (s.x == j && s.y == k)
{
data[i] = data[n - 1];
list.RemoveLast(1);
return;
}
}
}
public int Opposite(int j, int i)
{
var list = PrivateStars[i];
var n = list.UsedSize;
var data = list.Data;
for (var k = 0; k < n; ++k)
{
if (data[k].y == j)
{
return data[k].x;
}
}
return -1;
}
public void Flip(int i, int j)
{
var a = Opposite(i, j);
var b = Opposite(j, i);
RemoveTriangle(i, j, a);
RemoveTriangle(j, i, b);
AddTriangle(i, b, a);
AddTriangle(j, a, b);
}
public bool IsConstraint(int i, int j)
{
var e = new Int2(Mathf.Min(i, j), Mathf.Max(i, j));
return BinarySearch.EQ(Edges, e, 0, Edges.Length) >= 0;
}
public void Fill(List<int> triangles)
{
var n = PrivateStars.Length;
if (triangles.Capacity < n)
{
triangles.Capacity = n;
}
triangles.Clear();
for(var i = 0; i < n; ++i)
{
var list = PrivateStars[i];
var data = list.Data;
var m = list.UsedSize;
for(var j = 0; j < m; ++j)
{
var s = data[j];
if(i < Mathf.Min(s.x, s.y))
{
triangles.Add(i);
triangles.Add(s.x);
triangles.Add(s.y);
}
}
}
}
public void Fill(WorkBuffer<Int3> triangles)
{
var n = PrivateStars.Length;
triangles.Extend(n);
triangles.Clear();
for(var i = 0; i < n; ++i)
{
var list = PrivateStars[i];
var data = list.Data;
var m = list.UsedSize;
for(var j = 0; j < m; ++j)
{
var s = data[j];
if(i < Mathf.Min(s.x, s.y))
{
var v = new Int3(i, s.x, s.y);
triangles.Push(ref v);
}
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0ae927e5d9354637b7361e1a99ac6aa9
timeCreated: 1519790845

View File

@@ -0,0 +1,96 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Mikola Lysenko
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
namespace DA_Assets.SVGMeshUnity.Internals.Cdt2d
{
public class Triangulation
{
// https://github.com/mikolalysenko/cdt2d
public bool Delaunay = true;
public bool Interior = true;
public bool Exterior = true;
public bool Infinity = false;
public WorkBufferPool WorkBufferPool;
private MonotoneTriangulation MonotoneTriangulation = new MonotoneTriangulation();
private DelaunayRefine DelaunayRefine = new DelaunayRefine();
private Filter Filter = new Filter();
public void BuildTriangles(MeshData data)
{
//Handle trivial case
if ((!Interior && !Exterior) || data.Vertices.Count == 0)
{
return;
}
//Construct initial triangulation
MonotoneTriangulation.WorkBufferPool = WorkBufferPool;
MonotoneTriangulation.BuildTriangles(data);
//If delaunay refinement needed, then improve quality by edge flipping
if (Delaunay || Interior != Exterior || Infinity)
{
//Index all of the cells to support fast neighborhood queries
var triangles = new Triangles(data);
//Run edge flipping
if (Delaunay)
{
DelaunayRefine.WorkBufferPool = WorkBufferPool;
DelaunayRefine.RefineTriangles(triangles);
}
Filter.WorkBufferPool = WorkBufferPool;
Filter.Infinity = Infinity;
//Filter points
if (!Exterior)
{
Filter.Target = -1;
Filter.Do(triangles, data.Triangles);
return;
}
if (!Interior)
{
Filter.Target = 1;
Filter.Do(triangles, data.Triangles);
return;
}
if (Infinity)
{
Filter.Target = 0;
Filter.Do(triangles, data.Triangles);
return;
}
triangles.Fill(data.Triangles);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 781d3a8656524a829b4205bab46ef8de
timeCreated: 1519698011