Tessellators problem
Hello,
I believe there is a problem with the tessellations in this framework. The code below *compiles*, but does not display anything (this is tess.cs after removing the combine stuff because it generated errors). Also, the compiled examples do not work (the ones that came with the d/l. Is there a version of the framework where this works?
Thanks,
Mike
P.S. I'm using Microsoft Visual Studio 2005 with .NET Framework 2.0
#region License
/*
MIT License
Copyright 2003-2005 Tao Framework Team
http://www.taoframework.com
All rights reserved.
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.
*/
#endregion License
#region Original Credits / License
/*
* Copyright (c) 1993-1997, Silicon Graphics, Inc.
* ALL RIGHTS RESERVED
* Permission to use, copy, modify, and distribute this software for
* any purpose and without fee is hereby granted, provided that the above
* copyright notice appear in all copies and that both the copyright notice
* and this permission notice appear in supporting documentation, and that
* the name of Silicon Graphics, Inc. not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission.
*
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
*
* US Government Users Restricted Rights
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
* (c)(1)(ii) of the Rights in Technical Data and Computer Software
* clause at DFARS 252.227-7013 and/or in similar or successor
* clauses in the FAR or the DOD or NASA FAR Supplement.
* Unpublished-- rights reserved under the copyright laws of the
* United States. Contractor/manufacturer is Silicon Graphics,
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
*
* OpenGL(R) is a registered trademark of Silicon Graphics, Inc.
*/
#endregion Original Credits / License
using System;
using Tao.FreeGlut;
using Tao.OpenGl;
namespace test
{
#region Class Documentation
///
///
/// This program demonstrates polygon tessellation. Two tesselated objects are
/// drawn. The first is a rectangle with a triangular hole. The second is a
/// smooth shaded, self-intersecting star.
///
///
/// Note the exterior rectangle is drawn with its vertices in counter-clockwise
/// order, but its interior clockwise. Note the Combine callback is needed for
/// the self-intersecting star. Also note that removing the TessProperty for
/// the star will make the interior unshaded (WINDING_ODD).
///
///
///
///
/// Original Author: Silicon Graphics, Inc.
/// http://www.opengl.org/developers/code/examples/redbook/tess.c
///
///
/// C# Implementation: Randy Ridge
/// http://www.taoframework.com
///
///
#endregion Class Documentation
public sealed class Tess
{
// --- Fields ---
#region Private Fields
private static int startList;
#endregion Private Fields
// --- Entry Point ---
#region Run()
[STAThread]
public static void Run()
{
Glut.glutInit();
Glut.glutInitDisplayMode(Glut.GLUT_SINGLE | Glut.GLUT_RGB);
Glut.glutInitWindowSize(500, 500);
Glut.glutCreateWindow("Tess");
Init();
Glut.glutDisplayFunc(new Glut.DisplayCallback(Display));
Glut.glutKeyboardFunc(new Glut.KeyboardCallback(Keyboard));
Glut.glutReshapeFunc(new Glut.ReshapeCallback(Reshape));
Glut.glutMainLoop();
}
#endregion Run()
// --- Application Methods ---
#region Init()
private static void Init()
{
Glu.GLUtesselator tess;
double[][] rect = new double[4][] {
new double[] {50.0, 50.0, 0.0},
new double[] {200.0, 50.0, 0.0},
new double[] {200.0, 200.0, 0.0},
new double[] {50.0, 200.0, 0.0}
};
double[][] tri = new double[3][] {
new double[] {75.0, 75.0, 0.0},
new double[] {125.0, 175.0, 0.0},
new double[] {175.0, 75.0, 0.0}
};
double[][] star = new double[5][] {
new double[] {250.0, 50.0, 0.0, 1.0, 0.0, 1.0},
new double[] {325.0, 200.0, 0.0, 1.0, 1.0, 0.0},
new double[] {400.0, 50.0, 0.0, 0.0, 1.0, 1.0},
new double[] {250.0, 150.0, 0.0, 1.0, 0.0, 0.0},
new double[] {400.0, 150.0, 0.0, 0.0, 1.0, 0.0}
};
Gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
startList = Gl.glGenLists(1);
tess = Glu.gluNewTess();
Glu.gluTessCallback(tess, Glu.GLU_TESS_VERTEX, new Glu.TessVertexCallback1(Gl.glVertex3dv));
Glu.gluTessCallback(tess, Glu.GLU_TESS_BEGIN, new Glu.TessBeginCallback(Begin));
Glu.gluTessCallback(tess, Glu.GLU_TESS_END, new Glu.TessEndCallback(End));
Glu.gluTessCallback(tess, Glu.GLU_TESS_ERROR, new Glu.TessErrorCallback(Error));
// rectangle with triangular hole inside
Gl.glNewList(startList, Gl.GL_COMPILE);
Gl.glShadeModel(Gl.GL_FLAT);
Glu.gluTessBeginPolygon(tess, IntPtr.Zero);
Glu.gluTessBeginContour(tess);
Glu.gluTessVertex(tess, rect[0], rect[0]);
Glu.gluTessVertex(tess, rect[1], rect[1]);
Glu.gluTessVertex(tess, rect[2], rect[2]);
Glu.gluTessVertex(tess, rect[3], rect[3]);
Glu.gluTessEndContour(tess);
Glu.gluTessBeginContour(tess);
Glu.gluTessVertex(tess, tri[0], tri[0]);
Glu.gluTessVertex(tess, tri[1], tri[1]);
Glu.gluTessVertex(tess, tri[2], tri[2]);
Glu.gluTessEndContour(tess);
Glu.gluTessEndPolygon(tess);
Gl.glEndList();
//Glu.gluDeleteTess(tess);
}
#endregion Init()
// --- Callbacks ---
#region Begin(int which)
private static void Begin(int which)
{
Gl.glBegin(which);
}
#endregion Begin(int which)
#region Display()
private static void Display()
{
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);
Gl.glColor3f(1.0f, 1.0f, 1.0f);
Gl.glCallList(startList);
Gl.glFlush();
}
#endregion Display()
#region End()
private static void End()
{
Gl.glEnd();
}
#endregion End()
#region Error(int errorCode)
private static void Error(int errorCode)
{
Console.WriteLine("Tessellation Error: {0}", Glu.gluErrorString(errorCode));
Environment.Exit(1);
}
#endregion Error(int errorCode)
#region Keyboard(byte key, int x, int y)
private static void Keyboard(byte key, int x, int y)
{
switch (key)
{
case 27:
Environment.Exit(0);
break;
}
}
#endregion Keyboard(byte key, int x, int y)
#region Reshape(int w, int h)
private static void Reshape(int w, int h)
{
Gl.glViewport(0, 0, w, h);
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glLoadIdentity();
Glu.gluOrtho2D(0.0, (double)w, 0.0, (double)h);
}
#endregion Reshape(int w, int h)
}
}

It's a known bug with the
It's a known bug with the GLU bindings, I'm working on a fix.
------
OpenTK
Hi StApostol, have you find
Hi StApostol,
have you find a solution? I have the same problem.
Thanks!
Hi StApostol, I'm involved
Hi StApostol,
I'm involved with the game project with Spelltwister, the guy who started this thread. Its great to see that its a known issue and that its being worked on. That's encouraging. We've got a couple game projects with very large maps that it would seem need this to work.
Anything we can do to help things along?
Ryan S. Johnson
Guild of Blades Publishing Group
http://www.guildofblades.com
http://www.1483online.com
http://www.thermopylae-online.com
Sorry for not replying
Sorry for not replying earlier, I have been tied up with exams this last month. I have been trying to scavenge information regarding this problem from the old forums, this and this look related.
It seems that a fix was introduced at some point - can you try to use Glu.gluTessCallback1 instead of Glu.gluTessCallback and see if that works?
Sorry for not being more of help, I'm mostly listing this here lest I forget it when I start working on this.
------
OpenTK
Hello, I was able to get it
Hello,
I was able to get it to *almost* work using Glu.gluTessCallback (INSTEAD OF gluTessCallback1 which is what the example code used). It will do upto about 150 polygons before it stops working.
Hope this can help you find the fix. Also, if you need more info, please ask and I'll provide as much as I can.
Thanks,
Mike
Hello everybody! I'm
Hello everybody!
I'm experiencing the same problems.
Mike, how did you manage to obtain up to 150 polygons? could you post some code?
Any development ongoing? I'm not much familiar with the framework, but maybe I can help, if anyone has already identified the problem.
Claudio
Hallo everyone, meanwhile i
Hallo everyone,
meanwhile i have translated the Triangulator from Java3d into c#. It works for my perporse. If someone is intressed in, i can send the code.
I have spent quite some time
I have spent quite some time on this issue, and there are two things to observe:
a) GLU tesselation is very awkward in C#. Your approach sualk1000, is *much* better.
b) About 3/4 of issues with the tesselators stem from garbage collection. The code in this thread suffers from this, as the delegates look like temporary objects and are collected by the GC. The rest 1/4 are real incompatibilites with data marhalling. GLU expects arrays of pointers, which are difficult to marshal correctly from/to managed code.
Sualk1000, please consider open-sourcing your code. If you are comfortable with the MIT license, we could release it as a Tao "addon" library
To Tao devs:
I understand that Tao is a low-level collection of bindings but something like this would help *many* fellow developers! Maybe we could create an "official" list of Tao addons with useful utilities? This would fit nicely in OpenTK.Utilities which are compatible with Tao.OpenGL etc (fonts, texture/audio loaders and stuff like this.)
------
OpenTK
I'm really interested
I'm really interested sualk1000. Could you send me the code to germofer@ono.com?
hi sualk1000, yeah that
hi sualk1000,
yeah that sounds really interesting, is the code somewhere on the net?
cheers,
enix.
Dropping by to say the kind
Dropping by to say the kind folks at AGG# have implemented the GLU tesselator of Mesa3d in pure C#: https://sourceforge.net/projects/agg-sharp (check the code in SVN)
Hopefully, this will put an end to the problems with GLU tess, once and for all.
------
OpenTK
I've downloaded AGG
I've downloaded AGG Tesselator, but it isn't in a usable form yet, so I've made a wrapper dll from C++ to do the tesselation for me. It's not the fastest posible way because I'm copying de vertex into a local buffer in the dll, but it works, and it's better to have something that is not the fastest sollution than having nothing at all.
Can you please send me your
Can you please send me your code sualk1000?
holle at gmail dot com
thanks in advance
henrik
Hello sualk1000, I need a
Hello sualk1000, I need a tesselator working in C# and I saw your port of Java3d's one to C#, could you send me it?
arturoblas 4t gmail . c0m
Lots of thanks.
I've gotten the tessellation
I've gotten the tessellation to work before,
you simply need to pass a new object to gluTessVertex,
otherwise it'll just use the same object over and over or something, e.g.:
public void tessellate(float[,] points)
{
Glu.GLUTesselator tess;
/* ... */
for( int i = 0; i < points.Length; i++ )
{
double[] coords = new double[] { (double)points[i,0], (double)points[i,1], (double)points[i,2] };
Glu.gluTessVertex(tess, coords);
}
/* ... */
}
So far it has worked great for me but my only problem
so far is getting GLU_TESS_COMBINE to work properly, I haven't
been able to find a work around for that, other then writing a C wrapper.
Hey sualk1000, I would be
Hey sualk1000,
I would be interested in looking at your code if possible, just send to archangel_war at hotmail if you are still around and reading this.
To everyone in general: Does anyone know of any other C# tessellators that work?
I would greatly appreciate any help.
Edit: I should amend this to say that I need a tesselator that handles holes and not just a triangulator.
Hello Everyone, hier is the
Hello Everyone,
hier is the Code-Translation from the Java-Triangulator.
At the end ist an exmaple.
Good luck!
######################################
Class Triangulator
using System;
using System.Collections;
using Tao.OpenGl;
namespace ??????
{
// Referenced classes of package com.sun.j3d.utils.geometry:
// Bridge, Clean, Desperate, EarClip,
// GeometryInfo, ListNode, NoHash, Orientation,
// PntNode, Project, Simple, Triangle,
// Distance, Left, HeapNode
public class Triangulator
{
/**
* @deprecated Method Triangulator is deprecated
*/
public Triangulator()
{
faces = null;
loops = null;
chains = null;
points = null;
triangles = null;
list = null;
randomGen = null;
numPoints = 0;
maxNumPoints = 0;
numList = 0;
maxNumList = 0;
numLoops = 0;
maxNumLoops = 0;
numTriangles = 0;
maxNumTriangles = 0;
numFaces = 0;
numTexSets = 0;
firstNode = 0;
numChains = 0;
maxNumChains = 0;
pUnsorted = null;
maxNumPUnsorted = 0;
noHashingEdges = false;
noHashingPnts = false;
vtxList = null;
numVtxList = 0;
numReflex = 0;
distances = null;
maxNumDist = 0;
leftMost = null;
maxNumLeftMost = 0;
heap = null;
numHeap = 0;
maxNumHeap = 0;
numZero = 0;
maxNumPolyArea = 0;
polyArea = null;
stripCounts = null;
vertexIndices = null;
vertices = null;
colors = null;
normals = null;
ccwLoop = true;
earsRandom = true;
earsSorted = true;
epsilon = 9.9999999999999998E-013D;
earsRandom = false;
earsSorted = false;
}
/**
* @deprecated Method Triangulator is deprecated
*/
public Triangulator(int i)
{
faces = null;
loops = null;
chains = null;
points = null;
triangles = null;
list = null;
randomGen = null;
numPoints = 0;
maxNumPoints = 0;
numList = 0;
maxNumList = 0;
numLoops = 0;
maxNumLoops = 0;
numTriangles = 0;
maxNumTriangles = 0;
numFaces = 0;
numTexSets = 0;
firstNode = 0;
numChains = 0;
maxNumChains = 0;
pUnsorted = null;
maxNumPUnsorted = 0;
noHashingEdges = false;
noHashingPnts = false;
vtxList = null;
numVtxList = 0;
numReflex = 0;
distances = null;
maxNumDist = 0;
leftMost = null;
maxNumLeftMost = 0;
heap = null;
numHeap = 0;
maxNumHeap = 0;
numZero = 0;
maxNumPolyArea = 0;
polyArea = null;
stripCounts = null;
vertexIndices = null;
vertices = null;
colors = null;
normals = null;
ccwLoop = true;
earsRandom = true;
earsSorted = true;
epsilon = 9.9999999999999998E-013D;
switch (i)
{
case 0: // '\0'
earsRandom = false;
earsSorted = false;
break;
case 1: // '\001'
randomGen = new Random();
earsRandom = true;
earsSorted = false;
break;
case 2: // '\002'
earsRandom = false;
earsSorted = true;
break;
default:
earsRandom = false;
earsSorted = false;
break;
}
}
public void triangulate(Point3f[] vertices, int[] vertexIndices, Vector3f[] normals, int[] stripCounts, int[] faces)
{
int i2 = 0;
bool flag1 = false;
bool flag2 = false;
bool[] aflag = new bool[1];
bool[] aflag1 = new bool[1];
//geometryinfo.indexify();
this.vertices = vertices;
this.vertexIndices = vertexIndices;
this.normals = normals;
this.stripCounts = stripCounts;
this.faces = faces;
if(faces == null)
{
if(stripCounts == null)
Console.WriteLine("StripCounts is null! Don't know what to do.");
faces = new int[stripCounts.Length];
for(int i = 0; i < stripCounts.Length; i++)
faces[i] = 1;
}
numFaces = faces.Length;
numTexSets = 0;
maxNumLoops = 0;
maxNumList = 0;
maxNumPoints = 0;
maxNumDist = 0;
maxNumLeftMost = 0;
maxNumPUnsorted = 0;
for(int j = 0; j < faces.Length; j++)
{
maxNumLoops += faces[j];
for(int i1 = 0; i1 < faces[j];)
{
maxNumList += stripCounts[i2] + 1;
i1++;
i2++;
}
}
maxNumList += 20;
loops = new int[maxNumLoops];
list = new ListNode[maxNumList];
numVtxList = 0;
numReflex = 0;
numTriangles = 0;
numChains = 0;
numPoints = 0;
numLoops = 0;
numList = 0;
i2 = 0;
int j2 = 0;
for(int k = 0; k < faces.Length; k++)
{
for(int j1 = 0; j1 < faces[k];)
{
int k2 = makeLoopHeader();
int l2 = loops[k2];
for(int l1 = 0; l1 < stripCounts[i2]; l1++)
{
list[numList] = new ListNode(vertexIndices[j2]);
int i3 = numList++;
insertAfter(l2, i3);
list[i3].setCommonIndex(j2);
l2 = i3;
j2++;
}
deleteHook(k2);
j1++;
i2++;
}
}
maxNumTriangles = maxNumList / 2;
triangles = new Triangle[maxNumTriangles];
setEpsilon(1E-008D);
//printListData();
int i4 = 0;
bool flag4 = false;
for(int k1 = 0; k1 < numFaces; k1++)
{
ccwLoop = true;
aflag[0] = false;
int j4 = i4 + faces[k1];
bool flag;
if(faces[k1] > 1)
flag = true;
else
if(Simple.simpleFace(this, loops[i4]))
flag = false;
else
flag = true;
if(flag)
{
//Console.WriteLine("faces["+k1+"] "+faces[k1]);
for(int k4 = 0; k4 < faces[k1]; k4++)
preProcessList(i4 + k4);
Project.projectFace(this, i4, j4);
//Console.WriteLine("Before cleaning ...");
//printListData();
int l4 = Clean.cleanPolyhedralFace(this, i4, j4);
if(faces[k1] == 1)
Orientation.determineOrientation(this, loops[i4]);
else
Orientation.adjustOrientation(this, i4, j4);
if(faces[k1] > 1)
{
NoHash.prepareNoHashEdges(this, i4, j4);
} else
{
noHashingEdges = false;
noHashingPnts = false;
}
for(int l = i4; l < j4; l++)
EarClip.classifyAngles(this, loops[l]);
//Console.WriteLine("After classifyAngles ...");
//printListData();
if(faces[k1] > 1)
Bridge.constructBridges(this, i4, j4);
resetPolyList(loops[i4]);
NoHash.prepareNoHashPnts(this, i4);
EarClip.classifyEars(this, loops[i4]);
aflag[0] = false;
do
{
if(aflag[0])
break;
if(!EarClip.clipEar(this, aflag))
{
if(flag1)
{
int j3 = getNode();
resetPolyList(j3);
loops[i4] = j3;
if(Desperate.desperate(this, j3, i4, aflag))
{
if(!Desperate.letsHope(this, j3))
return;
} else
{
flag1 = false;
}
} else
{
bool flag3 = true;
int k3 = getNode();
resetPolyList(k3);
EarClip.classifyEars(this, k3);
flag1 = true;
}
} else
{
flag1 = false;
}
if(aflag[0])
{
int l3 = getNextChain(aflag1);
if(aflag1[0])
{
resetPolyList(l3);
loops[i4] = l3;
noHashingPnts = false;
NoHash.prepareNoHashPnts(this, i4);
EarClip.classifyEars(this, l3);
flag1 = false;
aflag[0] = false;
}
}
} while(true);
}
i4 = j4;
}
//writeTriangleToGeomInfo();
}
public void printVtxList()
{
Console.WriteLine("numReflex " + numReflex + " reflexVertices " + reflexVertices);
for(int i = 0; i < numVtxList; i++)
Console.WriteLine("" + i + " pnt " + vtxList[i].pnt + ", next " + vtxList[i].next);
}
public void printListData()
{
for(int i = 0; i < numList; i++)
Console.WriteLine("list[" + i +"].index "+ list[i].index + ", prev " + list[i].prev + ", next " + list[i].next + ", convex " + list[i].convex + ", vertexIndex " + list[i].vcntIndex);
}
public void preProcessList(int i)
{
resetPolyList(loops[i]);
int j = loops[i];
int k = j;
for (int l = list[k].next; l != j; l = list[k].next)
{
if (list[k].index == list[l].index)
{
if (l == loops[i])
loops[i] = list[l].next;
deleteLinks(l);
}
k = list[k].next;
}
}
public void writeTriangleToGeomInfo()
{
int i1 = 0;
int[] ai = new int[numTriangles * 3];
for(int i = 0; i < numTriangles; i++)
{
int i2 = list[triangles[i].v1].getCommonIndex();
ai[i1++] = vertexIndices[i2];
i2 = list[triangles[i].v2].getCommonIndex();
ai[i1++] = vertexIndices[i2];
i2 = list[triangles[i].v3].getCommonIndex();
ai[i1++] = vertexIndices[i2];
}
if(normals != null)
{
//int[] ai1 = normals;
//int[] ai3 = new int[numTriangles * 3];
//int j1 = 0;
//for (int j = 0; j < numTriangles; j++)
//{
// int j2 = list[triangles[j].v1].getCommonIndex();
// ai3[j1++] = ai1[j2];
// j2 = list[triangles[j].v2].getCommonIndex();
// ai3[j1++] = ai1[j2];
// j2 = list[triangles[j].v3].getCommonIndex();
// ai3[j1++] = ai1[j2];
//}
//gInfo.setNormalIndices(ai3);
}
if(colors != null)
{
//int k1 = 0;
////int[] ai2 = gInfo.getColorIndices();
//int[] ai4 = new int[numTriangles * 3];
//for(int k = 0; k < numTriangles; k++)
//{
// int k2 = list[triangles[k].v1].getCommonIndex();
// ai4[k1++] = ai2[k2];
// k2 = list[triangles[k].v2].getCommonIndex();
// ai4[k1++] = ai2[k2];
// k2 = list[triangles[k].v3].getCommonIndex();
// ai4[k1++] = ai2[k2];
//}
//gInfo.setColorIndices(ai4);
}
}
public void setEpsilon(double d)
{
epsilon = d;
}
public bool inPolyList(int i)
{
return i >= 0 && i < numList && numList <= maxNumList;
}
public void updateIndex(int i, int j)
{
list[i].index = j;
}
public int getAngle(int i)
{
return list[i].convex;
}
public void setAngle(int i, int j)
{
list[i].convex = j;
}
public void resetPolyList(int i)
{
firstNode = i;
}
public int getNode()
{
return firstNode;
}
public bool inLoopList(int i)
{
return i >= 0 && i < numLoops && numLoops <= maxNumLoops;
}
public void deleteHook(int i)
{
if(!inLoopList(i))
Console.WriteLine("Triangulator:deleteHook : Loop access out of range.");
int j = loops[i];
int k = list[j].next;
if(inPolyList(j) && inPolyList(k))
{
deleteLinks(j);
loops[i] = k;
} else
{
Console.WriteLine("Triangulator:deleteHook : List access out of range.");
}
}
public void deleteLinks(int i)
{
if(inPolyList(i) && inPolyList(list[i].prev) && inPolyList(list[i].next))
{
if(firstNode == i)
firstNode = list[i].next;
list[list[i].next].prev = list[i].prev;
list[list[i].prev].next = list[i].next;
list[i].prev = list[i].next = i;
} else
{
Console.WriteLine("Triangulator:deleteLinks : Access out of range.");
}
}
public void rotateLinks(int i, int j)
{
int l = list[i].next;
int i1 = list[j].next;
int k = list[i].next;
list[i].next = list[j].next;
list[j].next = k;
list[l].prev = j;
list[i1].prev = i;
}
public void storeChain(int i)
{
if(numChains >= maxNumChains)
{
maxNumChains += 20;
int[] ai = chains;
chains = new int[maxNumChains];
if(ai != null)
System.Array.Copy(ai, chains, ai.Length);
}
chains[numChains] = i;
numChains++;
}
public int getNextChain(bool[] aflag)
{
if (numChains > 0)
{
aflag[0] = true;
numChains--;
return chains[numChains];
}
else
{
aflag[0] = false;
numChains = 0;
return 0;
}
}
public void splitSplice(int i, int j, int k, int l)
{
list[i].next = l;
list[l].prev = i;
list[j].prev = k;
list[k].next = j;
}
public int makeHook()
{
int i = numList;
if(numList >= maxNumList)
{
maxNumList += 100;
ListNode[] alistnode = list;
list = new ListNode[maxNumList];
System.Array.Copy(alistnode, 0, list, 0, alistnode.Length);
}
list[numList] = new ListNode(-1);
list[numList].prev = i;
list[numList].next = i;
list[numList].index = -1;
numList++;
return i;
}
public int makeLoopHeader()
{
int j = makeHook();
if(numLoops >= maxNumLoops)
{
maxNumLoops += 20;
int[] ai = loops;
loops = new int[maxNumLoops];
System.Array.Copy(ai, 0, loops, 0, ai.Length);
}
loops[numLoops] = j;
int i = numLoops;
numLoops++;
return i;
}
public int makeNode(int i)
{
if(numList >= maxNumList)
{
maxNumList += 100;
ListNode[] alistnode = list;
list = new ListNode[maxNumList];
System.Array.Copy(alistnode, 0, list, 0, alistnode.Length);
}
list[numList] = new ListNode(i);
int j = numList;
list[numList].index = i;
list[numList].prev = -1;
list[numList].next = -1;
numList++;
return j;
}
public void insertAfter(int i, int j)
{
if(inPolyList(i) && inPolyList(j))
{
list[j].next = list[i].next;
list[j].prev = i;
list[i].next = j;
int k = list[j].next;
if(inPolyList(k))
list[k].prev = j;
else
Console.WriteLine("Triangulator:deleteHook : List access out of range.");
return;
} else
{
Console.WriteLine("Triangulator:deleteHook : List access out of range.");
return;
}
}
public int fetchNextData(int i)
{
return list[i].next;
}
public int fetchData(int i)
{
return list[i].index;
}
public int fetchPrevData(int i)
{
return list[i].prev;
}
public void swapLinks(int i)
{
int j = list[i].next;
list[i].next = list[i].prev;
list[i].prev = j;
int k = j;
int l;
for (; j != i; j = l)
{
l = list[j].next;
list[j].next = list[j].prev;
list[j].prev = l;
}
}
public void storeTriangle(int i, int j, int k)
{
if(numTriangles >= maxNumTriangles)
{
maxNumTriangles += 50;
Triangle[] atriangle = triangles;
triangles = new Triangle[maxNumTriangles];
if(atriangle != null)
System.Array.Copy(atriangle, 0, triangles, 0, atriangle.Length);
}
if(ccwLoop)
triangles[numTriangles] = new Triangle(i, j, k);
else
triangles[numTriangles] = new Triangle(j, i, k);
numTriangles++;
}
public void initPnts(int i)
{
if (maxNumPoints < i)
{
maxNumPoints = i;
points = new Point2f[maxNumPoints];
}
for (int j = 0; j < i; j++)
points[j] = new Point2f(0.0F, 0.0F);
numPoints = 0;
}
public bool inPointsList(int i)
{
return i >= 0 && i < numPoints && numPoints <= maxNumPoints;
}
public int storePoint(double d, double d1)
{
if(numPoints >= maxNumPoints)
{
maxNumPoints += 100;
Point2f[] apoint2f = points;
points = new Point2f[maxNumPoints];
if(apoint2f != null)
System.Array.Copy(apoint2f, 0, points, 0, apoint2f.Length);
}
points[numPoints] = new Point2f((float)d, (float)d1);
int i = numPoints;
numPoints++;
return i;
}
public int[] faces;
public int[] loops;
public int[] chains;
public Point2f[] points;
public Triangle[] triangles;
public ListNode[] list;
public Random randomGen;
public int numPoints;
public int maxNumPoints;
public int numList;
public int maxNumList;
public int numLoops;
public int maxNumLoops;
public int numTriangles;
public int maxNumTriangles;
public int numFaces;
public int numTexSets;
public int firstNode;
public int numChains;
public int maxNumChains;
public Point2f[] pUnsorted;
public int maxNumPUnsorted;
public bool noHashingEdges;
public bool noHashingPnts;
public int loopMin;
public int loopMax;
public PntNode[] vtxList;
public int numVtxList;
public int numReflex;
public int reflexVertices;
public Distance[] distances;
public int maxNumDist;
public Left[] leftMost;
public int maxNumLeftMost;
public HeapNode[] heap;
public int numHeap;
public int maxNumHeap;
public int numZero;
public int maxNumPolyArea;
public double[] polyArea;
public int[] stripCounts;
public int[] vertexIndices;
public Point3f[] vertices;
public Object[] colors;
public Vector3f[] normals;
public bool ccwLoop;
public bool earsRandom;
public bool earsSorted;
public int identCntr;
public double epsilon;
public static double ZERO = 1E-008D;
public static int EARS_SEQUENCE = 0;
public static int EARS_RANDOM = 1;
public static int EARS_SORTED = 2;
public static int INC_LIST_BK = 100;
public static int INC_LOOP_BK = 20;
public static int INC_TRI_BK = 50;
public static int INC_POINT_BK = 100;
public static int INC_DIST_BK = 50;
public static int DEBUG = 0;
}
public class Triangle
{
public Triangle(int i, int j, int k)
{
v1 = i;
v2 = j;
v3 = k;
}
public int v1;
public int v2;
public int v3;
}
public class Distance
{
public Distance()
{
}
public void copy(Distance distance)
{
ind = distance.ind;
dist = distance.dist;
}
public int ind;
public double dist;
}
public class HeapNode
{
public HeapNode()
{
}
public void copy(HeapNode heapnode)
{
index = heapnode.index;
prev = heapnode.prev;
next = heapnode.next;
ratio = heapnode.ratio;
}
public int index;
public int prev;
public int next;
public double ratio;
}
public class Left
{
public Left()
{
}
public void copy(Left left)
{
ind = left.ind;
index = left.index;
}
public int ind;
public int index;
}
public class ListNode
{
public ListNode(int i)
{
index = i;
prev = -1;
next = -1;
convex = 0;
vcntIndex = -1;
}
public void setCommonIndex(int i)
{
vcntIndex = i;
}
public int getCommonIndex()
{
return vcntIndex;
}
public int index;
public int prev;
public int next;
public int convex;
public int vcntIndex;
}
public class PntNode
{
public PntNode()
{
}
public int pnt;
public int next;
}
public class Point2f : Tuple2f
{
public Point2f()
{
this.x = 0f;
this.y = 0f;
}
public Point2f(float x, float y)
{
this.x = x;
this.y = y;
}
}
public class Point3f : Tuple3f
{
public Point3f()
{
}
public Point3f(double[] d)
{
x = (float)d[0];
y = (float)d[1];
z = (float)d[2];
}
public void set(double[] d)
{
x = (float)d[0];
y = (float)d[1];
z = (float)d[2];
}
}
public class Vector3f : Tuple3f
{
}
public class Bridge
{
public Bridge()
{
}
public static void constructBridges(Triangulator triangulator, int i, int j)
{
int[] ai = new int[1];
int[] ai1 = new int[1];
int[] ai2 = new int[1];
int[] ai3 = new int[1];
int[] ai4 = new int[1];
int[] ai5 = new int[1];
if(!triangulator.noHashingEdges)
Console.WriteLine("Bridge:constructBridges noHashingEdges is false");
if(j <= i)
Console.WriteLine("Bridge:constructBridges loopMax<=loopMin");
if(i < 0)
Console.WriteLine("Bridge:constructBridges loopMin<0");
if(j > triangulator.numLoops)
Console.WriteLine("Bridge:constructBridges loopMax>triRef.numLoops");
int k1 = j - i - 1;
if(k1 > triangulator.maxNumLeftMost)
{
triangulator.maxNumLeftMost = k1;
triangulator.leftMost = new Left[k1];
}
findLeftMostVertex(triangulator, triangulator.loops[i], ai1, ai);
int l = 0;
for(int k = i + 1; k < j; k++)
{
findLeftMostVertex(triangulator, triangulator.loops[k], ai5, ai4);
triangulator.leftMost[l] = new Left();
triangulator.leftMost[l].ind = ai5[0];
triangulator.leftMost[l].index = ai4[0];
l++;
}
sortLeft(triangulator.leftMost, k1);
int j1 = triangulator.numPoints + 2 * triangulator.numLoops;
triangulator.maxNumDist = j1;
triangulator.distances = new Distance[j1];
for(int l1 = 0; l1 < triangulator.maxNumDist; l1++)
triangulator.distances[l1] = new Distance();
for(int i1 = 0; i1 < k1; i1++)
{
if(findBridge(triangulator, ai1[0], ai[0], triangulator.leftMost[i1].index, ai3, ai2));
if(ai2[0] == triangulator.leftMost[i1].index)
simpleBridge(triangulator, ai3[0], triangulator.leftMost[i1].ind);
else
insertBridge(triangulator, ai3[0], ai2[0], triangulator.leftMost[i1].ind, triangulator.leftMost[i1].index);
}
}
public static bool findBridge(Triangulator triangulator, int i, int j, int k, int[] ai, int[] ai1)
{
int j2 = 0;
Object obj = null;
ai[0] = i;
ai1[0] = j;
if(ai1[0] == k)
return true;
if(j2 >= triangulator.maxNumDist)
{
Triangulator _tmp = triangulator;
triangulator.maxNumDist += 50;
Distance[] adistance = triangulator.distances;
triangulator.distances = new Distance[triangulator.maxNumDist];
System.Array.Copy(adistance, 0, triangulator.distances, 0, adistance.Length);
for(int k3 = adistance.Length; k3 < triangulator.maxNumDist; k3++)
triangulator.distances[k3] = new Distance();
}
triangulator.distances[j2].dist = Numerics.baseLength(triangulator.points[k], triangulator.points[ai1[0]]);
triangulator.distances[j2].ind = ai[0];
j2++;
ai[0] = triangulator.fetchNextData(ai[0]);
for(ai1[0] = triangulator.fetchData(ai[0]); ai[0] != i; ai1[0] = triangulator.fetchData(ai[0]))
{
if(ai1[0] == k)
return true;
if(j2 >= triangulator.maxNumDist)
{
Triangulator _tmp1 = triangulator;
triangulator.maxNumDist += 50;
Distance[] adistance1 = triangulator.distances;
triangulator.distances = new Distance[triangulator.maxNumDist];
System.Array.Copy(adistance1, 0, triangulator.distances, 0, adistance1.Length);
for(int l3 = adistance1.Length; l3 < triangulator.maxNumDist; l3++)
triangulator.distances[l3] = new Distance();
}
triangulator.distances[j2].dist = Numerics.baseLength(triangulator.points[k], triangulator.points[ai1[0]]);
triangulator.distances[j2].ind = ai[0];
j2++;
ai[0] = triangulator.fetchNextData(ai[0]);
}
sortDistance(triangulator.distances, j2);
for(int l1 = 0; l1 < j2; l1++)
{
ai[0] = triangulator.distances[l1].ind;
ai1[0] = triangulator.fetchData(ai[0]);
if(ai1[0] > k)
continue;
int k2 = triangulator.fetchPrevData(ai[0]);
int l = triangulator.fetchData(k2);
int i3 = triangulator.fetchNextData(ai[0]);
int j1 = triangulator.fetchData(i3);
bool flag = triangulator.getAngle(ai[0]) > 0;
bool flag1 = Numerics.isInCone(triangulator, l, ai1[0], j1, k, flag);
if(!flag1)
continue;
BBox bbox = new BBox(triangulator, ai1[0], k);
if(!NoHash.noHashEdgeIntersectionExists(triangulator, bbox, -1, -1, ai[0], -1))
return true;
}
for(int i2 = 0; i2 < j2; i2++)
{
ai[0] = triangulator.distances[i2].ind;
ai1[0] = triangulator.fetchData(ai[0]);
int l2 = triangulator.fetchPrevData(ai[0]);
int i1 = triangulator.fetchData(l2);
int j3 = triangulator.fetchNextData(ai[0]);
int k1 = triangulator.fetchData(j3);
BBox bbox1 = new BBox(triangulator, ai1[0], k);
if(!NoHash.noHashEdgeIntersectionExists(triangulator, bbox1, -1, -1, ai[0], -1))
return true;
}
ai[0] = i;
ai1[0] = j;
return false;
}
public static void findLeftMostVertex(Triangulator triangulator, int i, int[] ai, int[] ai1)
{
int j = i;
int k = triangulator.fetchData(j);
ai[0] = j;
ai1[0] = k;
j = triangulator.fetchNextData(j);
for(int l = triangulator.fetchData(j); j != i; l = triangulator.fetchData(j))
{
if(l < ai1[0])
{
ai[0] = j;
ai1[0] = l;
} else
if(l == ai1[0] && triangulator.getAngle(j) < 0)
{
ai[0] = j;
ai1[0] = l;
}
j = triangulator.fetchNextData(j);
}
}
public static void simpleBridge(Triangulator triangulator, int i, int j)
{
triangulator.rotateLinks(i, j);
int i1 = triangulator.fetchData(i);
int l = triangulator.fetchNextData(i);
int l1 = triangulator.fetchData(l);
int k = triangulator.fetchPrevData(i);
int k1 = triangulator.fetchData(k);
int i2 = Numerics.isConvexAngle(triangulator, k1, i1, l1, i);
triangulator.setAngle(i, i2);
int j1 = triangulator.fetchData(j);
l = triangulator.fetchNextData(j);
l1 = triangulator.fetchData(l);
k = triangulator.fetchPrevData(j);
k1 = triangulator.fetchData(k);
i2 = Numerics.isConvexAngle(triangulator, k1, j1, l1, j);
triangulator.setAngle(j, i2);
}
static void insertBridge(Triangulator triangulator, int i, int j, int k, int l)
{
int i1 = triangulator.makeNode(j);
triangulator.insertAfter(i, i1);
int l2 = triangulator.list[i].getCommonIndex();
triangulator.list[i1].setCommonIndex(l2);
int j1 = triangulator.makeNode(l);
triangulator.insertAfter(k, j1);
l2 = triangulator.list[k].getCommonIndex();
triangulator.list[j1].setCommonIndex(l2);
triangulator.splitSplice(i, i1, k, j1);
int l1 = triangulator.fetchNextData(i);
int j2 = triangulator.fetchData(l1);
int k1 = triangulator.fetchPrevData(i);
int i2 = triangulator.fetchData(k1);
int k2 = Numerics.isConvexAngle(triangulator, i2, j, j2, i);
triangulator.setAngle(i, k2);
l1 = triangulator.fetchNextData(i1);
j2 = triangulator.fetchData(l1);
k1 = triangulator.fetchPrevData(i1);
i2 = triangulator.fetchData(k1);
k2 = Numerics.isConvexAngle(triangulator, i2, j, j2, i1);
triangulator.setAngle(i1, k2);
l1 = triangulator.fetchNextData(k);
j2 = triangulator.fetchData(l1);
k1 = triangulator.fetchPrevData(k);
i2 = triangulator.fetchData(k1);
k2 = Numerics.isConvexAngle(triangulator, i2, l, j2, k);
triangulator.setAngle(k, k2);
l1 = triangulator.fetchNextData(j1);
j2 = triangulator.fetchData(l1);
k1 = triangulator.fetchPrevData(j1);
i2 = triangulator.fetchData(k1);
k2 = Numerics.isConvexAngle(triangulator, i2, l, j2, j1);
triangulator.setAngle(j1, k2);
}
static int l_comp(Left left, Left left1)
{
if(left.index < left1.index)
return -1;
return left.index <= left1.index ? 0 : 1;
}
static int d_comp(Distance distance, Distance distance1)
{
if(distance.dist < distance1.dist)
return -1;
return distance.dist <= distance1.dist ? 0 : 1;
}
static void sortLeft(Left[] aleft, int i)
{
Left left = new Left();
for(int j = 0; j < i; j++)
{
for(int k = j + 1; k < i; k++)
if(l_comp(aleft[j], aleft[k]) > 0)
{
left.copy(aleft[j]);
aleft[j].copy(aleft[k]);
aleft[k].copy(left);
}
}
}
public static void sortDistance(Distance[] adistance, int i)
{
Distance distance = new Distance();
for(int j = 0; j < i; j++)
{
for(int k = j + 1; k < i; k++)
if(d_comp(adistance[j], adistance[k]) > 0)
{
distance.copy(adistance[j]);
adistance[j].copy(adistance[k]);
adistance[k].copy(distance);
}
}
}
}
public class Simple
{
public Simple()
{
}
public static bool simpleFace(Triangulator triangulator, int i)
{
int j = triangulator.fetchPrevData(i);
int j2 = triangulator.fetchData(j);
if(j == i)
{
Console.WriteLine("***** polygon with only one vertex?! *****\n");
return true;
}
int k = triangulator.fetchNextData(i);
int l1 = triangulator.fetchData(k);
if(j == k)
{
Console.WriteLine("***** polygon with only two vertices?! *****\n");
return true;
}
int l = triangulator.fetchNextData(k);
int i2 = triangulator.fetchData(l);
if(j == l)
{
int j1 = triangulator.fetchData(i);
triangulator.storeTriangle(i, k, l);
return true;
}
int i1 = triangulator.fetchNextData(l);
int k2 = triangulator.fetchData(i1);
if(j == i1)
{
triangulator.initPnts(5);
int k1 = triangulator.fetchData(i);
Point3f point3f = new Point3f();
Point3f point3f1 = new Point3f();
Point3f point3f2 = new Point3f();
Basic.vectorSub(triangulator.vertices[k1], triangulator.vertices[l1], point3f);
Basic.vectorSub(triangulator.vertices[i2], triangulator.vertices[l1], point3f1);
Basic.vectorProduct(point3f, point3f1, point3f2);
double d = Math.Abs(point3f2.x);
double d1 = Math.Abs(point3f2.y);
double d2 = Math.Abs(point3f2.z);
if(d2 >= d && d2 >= d1)
{
triangulator.points[1].x = triangulator.vertices[k1].x;
triangulator.points[1].y = triangulator.vertices[k1].y;
triangulator.points[2].x = triangulator.vertices[l1].x;
triangulator.points[2].y = triangulator.vertices[l1].y;
triangulator.points[3].x = triangulator.vertices[i2].x;
triangulator.points[3].y = triangulator.vertices[i2].y;
triangulator.points[4].x = triangulator.vertices[k2].x;
triangulator.points[4].y = triangulator.vertices[k2].y;
} else
if(d >= d1 && d >= d2)
{
triangulator.points[1].x = triangulator.vertices[k1].z;
triangulator.points[1].y = triangulator.vertices[k1].y;
triangulator.points[2].x = triangulator.vertices[l1].z;
triangulator.points[2].y = triangulator.vertices[l1].y;
triangulator.points[3].x = triangulator.vertices[i2].z;
triangulator.points[3].y = triangulator.vertices[i2].y;
triangulator.points[4].x = triangulator.vertices[k2].z;
triangulator.points[4].y = triangulator.vertices[k2].y;
} else
{
triangulator.points[1].x = triangulator.vertices[k1].x;
triangulator.points[1].y = triangulator.vertices[k1].z;
triangulator.points[2].x = triangulator.vertices[l1].x;
triangulator.points[2].y = triangulator.vertices[l1].z;
triangulator.points[3].x = triangulator.vertices[i2].x;
triangulator.points[3].y = triangulator.vertices[i2].z;
triangulator.points[4].x = triangulator.vertices[k2].x;
triangulator.points[4].y = triangulator.vertices[k2].z;
}
triangulator.numPoints = 5;
int l2 = Numerics.orientation(triangulator, 1, 2, 3);
int i3 = Numerics.orientation(triangulator, 1, 3, 4);
if(l2 > 0 && i3 > 0 || l2 < 0 && i3 < 0)
{
triangulator.storeTriangle(i, k, l);
triangulator.storeTriangle(i, l, i1);
} else
{
triangulator.storeTriangle(k, l, i1);
triangulator.storeTriangle(k, i1, i);
}
return true;
} else
{
return false;
}
}
}
public class EarClip
{
public EarClip()
{
}
public static void classifyAngles(Triangulator triangulator, int i)
{
int k = i;
int j1 = triangulator.fetchData(k);
int j = triangulator.fetchPrevData(k);
int i1 = triangulator.fetchData(j);
do
{
int l = triangulator.fetchNextData(k);
int k1 = triangulator.fetchData(l);
int l1 = Numerics.isConvexAngle(triangulator, i1, j1, k1, k);
triangulator.setAngle(k, l1);
i1 = j1;
j1 = k1;
k = l;
} while(k != i);
}
public static void classifyEars(Triangulator triangulator, int i)
{
int[] ai = new int[1];
int[] ai1 = new int[1];
double[] ad = new double[1];
Heap.initHeap(triangulator);
int j = i;
int k = triangulator.fetchData(j);
do
{
if(triangulator.getAngle(j) > 0 && isEar(triangulator, j, ai, ai1, ad))
Heap.dumpOnHeap(triangulator, ad[0], j, ai[0], ai1[0]);
j = triangulator.fetchNextData(j);
int l = triangulator.fetchData(j);
} while(j != i);
}
public static bool isEar(Triangulator triangulator, int i, int[] ai, int[] ai1, double[] ad)
{
int l = triangulator.fetchData(i);
ai1[0] = triangulator.fetchNextData(i);
int i1 = triangulator.fetchData(ai1[0]);
int l1 = triangulator.fetchNextData(ai1[0]);
int j1 = triangulator.fetchData(l1);
ai[0] = triangulator.fetchPrevData(i);
int k = triangulator.fetchData(ai[0]);
int k1 = triangulator.fetchPrevData(ai[0]);
int j = triangulator.fetchData(k1);
if(k == i1 || k == l || l == i1 || triangulator.getAngle(i) == 2)
{
ad[0] = 0.0D;
return true;
}
if(j == i1)
if(triangulator.getAngle(k1) < 0 || triangulator.getAngle(ai1[0]) < 0)
{
ad[0] = 0.0D;
return true;
} else
{
return false;
}
if(k == j1)
if(triangulator.getAngle(ai[0]) < 0 || triangulator.getAngle(l1) < 0)
{
ad[0] = 0.0D;
return true;
} else
{
return false;
}
bool flag = triangulator.getAngle(ai[0]) > 0;
bool flag1 = Numerics.isInCone(triangulator, j, k, l, i1, flag);
if(!flag1)
return false;
flag = triangulator.getAngle(ai1[0]) > 0;
flag1 = Numerics.isInCone(triangulator, l, i1, j1, k, flag);
if(flag1)
{
BBox bbox = new BBox(triangulator, k, i1);
if(!NoHash.noHashIntersectionExists(triangulator, l, i, i1, k, bbox))
{
if(triangulator.earsSorted)
ad[0] = Numerics.getRatio(triangulator, k, i1, l);
else
ad[0] = 1.0D;
return true;
}
}
return false;
}
public static bool clipEar(Triangulator triangulator, bool[] aflag)
{
double[] ad = new double[1];
int[] ai = new int[1];
int[] ai1 = new int[1];
int[] ai2 = new int[1];
int[] ai3 = new int[1];
int[] ai4 = new int[1];
int[] ai5 = new int[1];
bool flag = false;
int j;
int k;
int j1;
int l1;
do
{
if(!Heap.deleteFromHeap(triangulator, ai5, ai1, ai3))
return false;
j = triangulator.fetchPrevData(ai5[0]);
j1 = triangulator.fetchData(j);
k = triangulator.fetchNextData(ai5[0]);
l1 = triangulator.fetchData(k);
} while(ai1[0] != j || ai3[0] != k);
int k1 = triangulator.fetchData(ai5[0]);
triangulator.deleteLinks(ai5[0]);
triangulator.storeTriangle(j, ai5[0], k);
int i = triangulator.fetchPrevData(j);
int i1 = triangulator.fetchData(i);
if(i == k)
{
aflag[0] = true;
return true;
}
int j2 = Numerics.isConvexAngle(triangulator, i1, j1, l1, j);
int l = triangulator.fetchNextData(k);
int i2 = triangulator.fetchData(l);
int k2 = Numerics.isConvexAngle(triangulator, j1, l1, i2, k);
if(j1 != l1)
{
if(j2 >= 0 && triangulator.getAngle(j) < 0)
NoHash.deleteReflexVertex(triangulator, j);
if(k2 >= 0 && triangulator.getAngle(k) < 0)
NoHash.deleteReflexVertex(triangulator, k);
} else
if(j2 >= 0 && triangulator.getAngle(j) < 0)
NoHash.deleteReflexVertex(triangulator, j);
else
if(k2 >= 0 && triangulator.getAngle(k) < 0)
NoHash.deleteReflexVertex(triangulator, k);
triangulator.setAngle(j, j2);
triangulator.setAngle(k, k2);
if(j2 > 0 && isEar(triangulator, j, ai, ai2, ad))
Heap.insertIntoHeap(triangulator, ad[0], j, ai[0], ai2[0]);
if(k2 > 0 && isEar(triangulator, k, ai2, ai4, ad))
Heap.insertIntoHeap(triangulator, ad[0], k, ai2[0], ai4[0]);
i = triangulator.fetchPrevData(j);
i1 = triangulator.fetchData(i);
l = triangulator.fetchNextData(k);
i2 = triangulator.fetchData(l);
if(i == l)
{
triangulator.storeTriangle(j, k, l);
aflag[0] = true;
} else
{
aflag[0] = false;
}
return true;
}
}
public class Desperate
{
public Desperate()
{
}
public static bool desperate(Triangulator triangulator, int i, int j, bool[] aflag)
{
int[] ai = new int[1];
int[] ai1 = new int[1];
int[] ai2 = new int[1];
int[] ai3 = new int[1];
int[] ai4 = new int[1];
int[] ai5 = new int[1];
int[] ai6 = new int[1];
int[] ai7 = new int[1];
aflag[0] = false;
if(existsCrossOver(triangulator, i, ai4, ai, ai5, ai1, ai6, ai2, ai7, ai3))
{
handleCrossOver(triangulator, ai4[0], ai[0], ai5[0], ai1[0], ai6[0], ai2[0], ai7[0], ai3[0]);
return false;
}
NoHash.prepareNoHashEdges(triangulator, j, j + 1);
if(existsSplit(triangulator, i, ai4, ai, ai5, ai1))
{
handleSplit(triangulator, ai4[0], ai[0], ai5[0], ai1[0]);
aflag[0] = true;
return false;
} else
{
return true;
}
}
public static bool existsCrossOver(Triangulator triangulator, int i, int[] ai, int[] ai1, int[] ai2, int[] ai3, int[] ai4, int[] ai5,
int[] ai6, int[] ai7)
{
ai[0] = i;
ai1[0] = triangulator.fetchData(ai[0]);
ai2[0] = triangulator.fetchNextData(ai[0]);
ai3[0] = triangulator.fetchData(ai2[0]);
ai4[0] = triangulator.fetchNextData(ai2[0]);
ai5[0] = triangulator.fetchData(ai4[0]);
ai6[0] = triangulator.fetchNextData(ai4[0]);
ai7[0] = triangulator.fetchData(ai6[0]);
do
{
BBox bbox = new BBox(triangulator, ai1[0], ai3[0]);
BBox bbox1 = new BBox(triangulator, ai5[0], ai7[0]);
if(bbox.BBoxOverlap(bbox1) && Numerics.segIntersect(triangulator, bbox.imin, bbox.imax, bbox1.imin, bbox1.imax, -1))
return true;
ai[0] = ai2[0];
ai1[0] = ai3[0];
ai2[0] = ai4[0];
ai3[0] = ai5[0];
ai4[0] = ai6[0];
ai5[0] = ai7[0];
ai6[0] = triangulator.fetchNextData(ai4[0]);
ai7[0] = triangulator.fetchData(ai6[0]);
} while(ai[0] != i);
return false;
}
public static void handleCrossOver(Triangulator triangulator, int i, int j, int k, int l, int i1, int j1, int k1,
int l1)
{
int i2 = triangulator.getAngle(i);
int j2 = triangulator.getAngle(k1);
bool flag;
if(i2 < j2)
flag = true;
else
if(i2 > j2)
flag = false;
else
if(triangulator.earsSorted)
{
double d = Numerics.getRatio(triangulator, j1, l1, j);
double d1 = Numerics.getRatio(triangulator, j, l, l1);
if(d1 < d)
flag = false;
else
flag = true;
} else
{
flag = true;
}
if(flag)
{
triangulator.deleteLinks(k);
triangulator.storeTriangle(i, k, i1);
triangulator.setAngle(i1, 1);
Heap.insertIntoHeap(triangulator, 0.0D, i1, i, k1);
} else
{
triangulator.deleteLinks(i1);
triangulator.storeTriangle(k, i1, k1);
triangulator.setAngle(k, 1);
Heap.insertIntoHeap(triangulator, 0.0D, k, i, k1);
}
}
public static bool letsHope(Triangulator triangulator, int i)
{
int l = i;
int i2 = triangulator.fetchData(l);
do
{
if(triangulator.getAngle(l) > 0)
{
int j = triangulator.fetchPrevData(l);
int k1 = triangulator.fetchData(j);
int i1 = triangulator.fetchNextData(l);
int j2 = triangulator.fetchData(i1);
Heap.insertIntoHeap(triangulator, 0.0D, l, j, i1);
return true;
}
l = triangulator.fetchNextData(l);
i2 = triangulator.fetchData(l);
} while(l != i);
triangulator.setAngle(i, 1);
int k = triangulator.fetchPrevData(i);
int l1 = triangulator.fetchData(k);
int j1 = triangulator.fetchNextData(i);
int k2 = triangulator.fetchData(j1);
Heap.insertIntoHeap(triangulator, 0.0D, i, k, j1);
i2 = triangulator.fetchData(i);
return true;
}
public static bool existsSplit(Triangulator triangulator, int i, int[] ai, int[] ai1, int[] ai2, int[] ai3)
{
if(triangulator.numPoints > triangulator.maxNumDist)
{
triangulator.maxNumDist = triangulator.numPoints;
triangulator.distances = new Distance[triangulator.maxNumDist];
for(int i2 = 0; i2 < triangulator.maxNumDist; i2++)
triangulator.distances[i2] = new Distance();
}
ai[0] = i;
ai1[0] = triangulator.fetchData(ai[0]);
int k = triangulator.fetchNextData(ai[0]);
int j1 = triangulator.fetchData(k);
int l = triangulator.fetchNextData(k);
int k1 = triangulator.fetchData(l);
int j = triangulator.fetchPrevData(ai[0]);
int i1 = triangulator.fetchData(j);
if(foundSplit(triangulator, l, k1, j, ai[0], ai1[0], i1, j1, ai2, ai3))
return true;
i1 = ai1[0];
ai[0] = k;
ai1[0] = j1;
k = l;
j1 = k1;
l = triangulator.fetchNextData(k);
for(int l1 = triangulator.fetchData(l); l != i; l1 = triangulator.fetchData(l))
{
if(foundSplit(triangulator, l, l1, i, ai[0], ai1[0], i1, j1, ai2, ai3))
return true;
i1 = ai1[0];
ai[0] = k;
ai1[0] = j1;
k = l;
j1 = l1;
l = triangulator.fetchNextData(k);
}
return false;
}
public static int windingNumber(Triangulator triangulator, int i, Point2f point2f)
{
int k = triangulator.fetchData(i);
int j = triangulator.fetchNextData(i);
int l = triangulator.fetchData(j);
double d;
for(d = Numerics.angle(triangulator, point2f, triangulator.points[k], triangulator.points[l]); j != i; d += Numerics.angle(triangulator, point2f, triangulator.points[k], triangulator.points[l]))
{
k = l;
j = triangulator.fetchNextData(j);
l = triangulator.fetchData(j);
}
d += 3.1415926535897931D;
int i1 = (int)(d / 6.2831853071795862D);
return i1;
}
public static bool foundSplit(Triangulator triangulator, int i, int j, int k, int l, int i1, int j1, int k1,
int[] ai, int[] ai1)
{
int l1 = 0;
do
{
triangulator.distances[l1].dist = Numerics.baseLength(triangulator.points[i1], triangulator.points[j]);
triangulator.distances[l1].ind = i;
l1++;
i = triangulator.fetchNextData(i);
j = triangulator.fetchData(i);
} while(i != k);
Bridge.sortDistance(triangulator.distances, l1);
for(int i2 = 0; i2 < l1; i2++)
{
ai[0] = triangulator.distances[i2].ind;
ai1[0] = triangulator.fetchData(ai[0]);
if(i1 == ai1[0])
continue;
int l2 = triangulator.fetchPrevData(ai[0]);
int j2 = triangulator.fetchData(l2);
int i3 = triangulator.fetchNextData(ai[0]);
int k2 = triangulator.fetchData(i3);
bool flag = triangulator.getAngle(ai[0]) > 0;
bool flag1 = Numerics.isInCone(triangulator, j2, ai1[0], k2, i1, flag);
if(!flag1)
continue;
flag = triangulator.getAngle(l) > 0;
flag1 = Numerics.isInCone(triangulator, j1, i1, k1, ai1[0], flag);
if(!flag1)
continue;
BBox bbox = new BBox(triangulator, i1, ai1[0]);
if(NoHash.noHashEdgeIntersectionExists(triangulator, bbox, -1, -1, l, -1))
continue;
Point2f point2f = new Point2f();
Basic.vectorAdd2D(triangulator.points[i1], triangulator.points[ai1[0]], point2f);
Basic.multScalar2D(0.5D, point2f);
if(windingNumber(triangulator, k, point2f) == 1)
return true;
}
return false;
}
public static void handleSplit(Triangulator triangulator, int i, int j, int k, int l)
{
int l2 = -1;
int i1 = triangulator.makeNode(j);
triangulator.insertAfter(i, i1);
l2 = triangulator.list[i].getCommonIndex();
triangulator.list[i1].setCommonIndex(l2);
int j1 = triangulator.makeNode(l);
triangulator.insertAfter(k, j1);
l2 = triangulator.list[k].getCommonIndex();
triangulator.list[j1].setCommonIndex(l2);
triangulator.splitSplice(i, i1, k, j1);
triangulator.storeChain(i);
triangulator.storeChain(k);
int l1 = triangulator.fetchNextData(i);
int j2 = triangulator.fetchData(l1);
int k1 = triangulator.fetchPrevData(i);
int i2 = triangulator.fetchData(k1);
int k2 = Numerics.isConvexAngle(triangulator, i2, j, j2, i);
triangulator.setAngle(i, k2);
l1 = triangulator.fetchNextData(i1);
j2 = triangulator.fetchData(l1);
k1 = triangulator.fetchPrevData(i1);
i2 = triangulator.fetchData(k1);
k2 = Numerics.isConvexAngle(triangulator, i2, j, j2, i1);
triangulator.setAngle(i1, k2);
l1 = triangulator.fetchNextData(k);
j2 = triangulator.fetchData(l1);
k1 = triangulator.fetchPrevData(k);
i2 = triangulator.fetchData(k1);
k2 = Numerics.isConvexAngle(triangulator, i2, l, j2, k);
triangulator.setAngle(k, k2);
l1 = triangulator.fetchNextData(j1);
j2 = triangulator.fetchData(l1);
k1 = triangulator.fetchPrevData(j1);
i2 = triangulator.fetchData(k1);
k2 = Numerics.isConvexAngle(triangulator, i2, l, j2, j1);
triangulator.setAngle(j1, k2);
}
}
public class NoHash
{
public NoHash()
{
}
public static void insertAfterVtx(Triangulator triangulator, int i)
{
if(triangulator.vtxList == null)
{
int j = Math.Max(triangulator.numVtxList + 1, 100);
triangulator.vtxList = new PntNode[j];
} else
if(triangulator.numVtxList >= triangulator.vtxList.Length)
{
int k = Math.Max(triangulator.numVtxList + 1, triangulator.vtxList.Length + 100);
PntNode[] apntnode = triangulator.vtxList;
triangulator.vtxList = new PntNode[k];
System.Array.Copy(apntnode, 0, triangulator.vtxList, 0, apntnode.Length);
}
triangulator.vtxList[triangulator.numVtxList] = new PntNode();
triangulator.vtxList[triangulator.numVtxList].pnt = i;
triangulator.vtxList[triangulator.numVtxList].next = triangulator.reflexVertices;
triangulator.reflexVertices = triangulator.numVtxList;
triangulator.numVtxList++;
triangulator.numReflex++;
}
public static void deleteFromList(Triangulator triangulator, int i)
{
if(triangulator.numReflex == 0)
return;
int j = triangulator.reflexVertices;
if(!inVtxList(triangulator, j))
Console.WriteLine("NoHash:deleteFromList. Problem :Not is InVtxList ..." + j);
int l = triangulator.vtxList[j].pnt;
if(l == i)
{
triangulator.reflexVertices = triangulator.vtxList[j].next;
triangulator.numReflex--;
} else
{
for(int k = triangulator.vtxList[j].next; k != -1;)
{
if(!inVtxList(triangulator, k))
Console.WriteLine("NoHash:deleteFromList. Problem :Not is InVtxList ..." + k);
int i1 = triangulator.vtxList[k].pnt;
if(i1 == i)
{
triangulator.vtxList[j].next = triangulator.vtxList[k].next;
k = -1;
triangulator.numReflex--;
} else
{
j = k;
k = triangulator.vtxList[j].next;
}
}
}
}
public static bool inVtxList(Triangulator triangulator, int i)
{
return 0 <= i && i < triangulator.numVtxList;
}
public static void freeNoHash(Triangulator triangulator)
{
triangulator.noHashingEdges = false;
triangulator.noHashingPnts = false;
triangulator.numVtxList = 0;
}
public static void prepareNoHashEdges(Triangulator triangulator, int i, int j)
{
triangulator.loopMin = i;
triangulator.loopMax = j;
triangulator.noHashingEdges = true;
}
public static void prepareNoHashPnts(Triangulator triangulator, int i)
{
triangulator.numVtxList = 0;
triangulator.reflexVertices = -1;
int j = triangulator.loops[i];
int k = j;
triangulator.numReflex = 0;
int l = triangulator.fetchData(k);
do
{
if(triangulator.getAngle(k) < 0)
insertAfterVtx(triangulator, k);
k = triangulator.fetchNextData(k);
int i1 = triangulator.fetchData(k);
} while(k != j);
triangulator.noHashingPnts = true;
}
public static bool noHashIntersectionExists(Triangulator triangulator, int i, int j, int k, int l, BBox bbox)
{
int[] ai = new int[1];
if(!triangulator.noHashingPnts)
Console.WriteLine("NoHash:noHashIntersectionExists noHashingPnts is false");
if(triangulator.numReflex <= 0)
return false;
if(i < bbox.imin)
bbox.imin = i;
else
if(i > bbox.imax)
bbox.imax = i;
double d = triangulator.points[i].y;
if(d < bbox.ymin)
bbox.ymin = d;
else
if(d > bbox.ymax)
bbox.ymax = d;
int k1 = triangulator.reflexVertices;
bool flag = false;
do
{
int i1 = triangulator.vtxList[k1].pnt;
int l1 = triangulator.fetchData(i1);
if(bbox.pntInBBox(triangulator, l1))
{
int j1 = triangulator.fetchNextData(i1);
int i2 = triangulator.fetchData(j1);
if(i1 != j && i1 != j1)
if(l1 == i)
{
if(Degenerate.handleDegeneracies(triangulator, i, j, k, l, l1, i1))
return true;
} else
if(l1 != k && l1 != l)
{
bool flag1 = Numerics.vtxInTriangle(triangulator, i, k, l, l1, ai);
if(flag1)
return true;
}
}
k1 = triangulator.vtxList[k1].next;
} while(k1 != -1);
return false;
}
public static void deleteReflexVertex(Triangulator triangulator, int i)
{
deleteFromList(triangulator, i);
}
public static bool noHashEdgeIntersectionExists(Triangulator triangulator, BBox bbox, int i, int j, int k, int l)
{
if(!triangulator.noHashingEdges)
Console.WriteLine("NoHash:noHashEdgeIntersectionExists noHashingEdges is false");
triangulator.identCntr = 0;
for(int k1 = triangulator.loopMin; k1 < triangulator.loopMax; k1++)
{
int i1 = triangulator.loops[k1];
int j1 = i1;
int l1 = triangulator.fetchData(j1);
do
{
j1 = triangulator.fetchNextData(j1);
int i2 = triangulator.fetchData(j1);
BBox bbox1 = new BBox(triangulator, l1, i2);
if(bbox.BBoxOverlap(bbox1) && Numerics.segIntersect(triangulator, bbox.imin, bbox.imax, bbox1.imin, bbox1.imax, l))
return true;
l1 = i2;
} while(j1 != i1);
}
if(triangulator.identCntr >= 4)
return BottleNeck.checkBottleNeck(triangulator, l, i, j, k);
else
return false;
}
public static int NIL = -1;
}
public class Orientation
{
public Orientation()
{
}
public static void adjustOrientation(Triangulator triangulator, int i, int j)
{
if(i >= j)
Console.WriteLine("Orientation:adjustOrientation Problem i1>=i2 !!!");
if(triangulator.numLoops >= triangulator.maxNumPolyArea)
{
triangulator.maxNumPolyArea = triangulator.numLoops;
double[] ad = triangulator.polyArea;
triangulator.polyArea = new double[triangulator.maxNumPolyArea];
if(ad != null)
System.Array.Copy(ad, 0, triangulator.polyArea, 0, ad.Length);
}
for(int k = i; k < j; k++)
{
int k1 = triangulator.loops[k];
triangulator.polyArea[k] = polygonArea(triangulator, k1);
}
double d = Math.Abs(triangulator.polyArea[i]);
int j1 = i;
for(int l = i + 1; l < j; l++)
if(d < Math.Abs(triangulator.polyArea[l]))
{
d = Math.Abs(triangulator.polyArea[l]);
j1 = l;
}
if(j1 != i)
{
int l1 = triangulator.loops[i];
triangulator.loops[i] = triangulator.loops[j1];
triangulator.loops[j1] = l1;
double d1 = triangulator.polyArea[i];
triangulator.polyArea[i] = triangulator.polyArea[j1];
triangulator.polyArea[j1] = d1;
}
if(triangulator.polyArea[i] < 0.0D)
triangulator.swapLinks(triangulator.loops[i]);
for(int i1 = i + 1; i1 < j; i1++)
if(triangulator.polyArea[i1] > 0.0D)
triangulator.swapLinks(triangulator.loops[i1]);
}
public static double polygonArea(Triangulator triangulator, int i)
{
int j = 0;
double d = 0.0D;
double d1 = 0.0D;
int k = i;
int j1 = triangulator.fetchData(k);
int l = triangulator.fetchNextData(k);
int l1 = triangulator.fetchData(l);
d = Numerics.stableDet2D(triangulator, j, j1, l1);
k = l;
for(int k1 = l1; k != i; k1 = l1)
{
int i1 = triangulator.fetchNextData(k);
l1 = triangulator.fetchData(i1);
double d2 = Numerics.stableDet2D(triangulator, j, k1, l1);
d += d2;
k = i1;
}
return d;
}
public static void determineOrientation(Triangulator triangulator, int i)
{
double d = polygonArea(triangulator, i);
if(d < 0.0D)
{
triangulator.swapLinks(i);
triangulator.ccwLoop = false;
}
}
}
public class BBox
{
public BBox(Triangulator triangulator, int i, int j)
{
imin = Math.Min(i, j);
imax = Math.Max(i, j);
ymin = Math.Min(triangulator.points[imin].y, triangulator.points[imax].y);
ymax = Math.Max(triangulator.points[imin].y, triangulator.points[imax].y);
}
public bool pntInBBox(Triangulator triangulator, int i)
{
return imax >= i ? imin <= i ? ymax >= (double)triangulator.points[i].y ? ymin <= (double)triangulator.points[i].y : false : false : false;
}
public bool BBoxOverlap(BBox bbox)
{
return imax >= bbox.imin ? imin <= bbox.imax ? ymax >= bbox.ymin ? ymin <= bbox.ymax : false : false : false;
}
public bool BBoxContained(BBox bbox)
{
return imin <= bbox.imin && imax >= bbox.imax && ymin <= bbox.ymin && ymax >= bbox.ymax;
}
public bool BBoxIdenticalLeaf(BBox bbox)
{
return imin == bbox.imin && imax == bbox.imax;
}
public void BBoxUnion(BBox bbox, BBox bbox1)
{
bbox1.imin = Math.Min(imin, bbox.imin);
bbox1.imax = Math.Max(imax, bbox.imax);
bbox1.ymin = Math.Min(ymin, bbox.ymin);
bbox1.ymax = Math.Max(ymax, bbox.ymax);
}
public double BBoxArea(Triangulator triangulator)
{
return (double)(triangulator.points[imax].x - triangulator.points[imin].x) * (ymax - ymin);
}
public int imin;
public int imax;
public double ymin;
public double ymax;
}
public class Project
{
public Project()
{
}
public static void projectFace(Triangulator triangulator, int i, int j)
{
Vector3f vector3f = new Vector3f();
Vector3f vector3f1 = new Vector3f();
determineNormal(triangulator, triangulator.loops[i], vector3f);
int l = i + 1;
if (l < j)
{
for (int k = l; k < j; k++)
{
determineNormal(triangulator, triangulator.loops[k], vector3f1);
if (Basic.dotProduct(vector3f, vector3f1) < 0.0D)
Basic.invertVector(vector3f1);
Basic.vectorAdd(vector3f, vector3f1, vector3f);
}
double d = Basic.lengthL2(vector3f);
if (Numerics.gt(d, 1E-008D))
{
Basic.divScalar(d, vector3f);
}
else
{
vector3f.x = vector3f.y = 0.0F;
vector3f.z = 1.0F;
}
}
projectPoints(triangulator, i, j, vector3f);
}
public static void determineNormal(Triangulator triangulator, int i, Vector3f vector3f)
{
int k = i;
int j1 = triangulator.fetchData(k);
int j = triangulator.fetchPrevData(k);
int i1 = triangulator.fetchData(j);
int l = triangulator.fetchNextData(k);
int k1 = triangulator.fetchData(l);
Vector3f vector3f2 = new Vector3f();
Basic.vectorSub(triangulator.vertices[i1], triangulator.vertices[j1], vector3f2);
Vector3f vector3f3 = new Vector3f();
Basic.vectorSub(triangulator.vertices[k1], triangulator.vertices[j1], vector3f3);
Vector3f vector3f1 = new Vector3f();
Basic.vectorProduct(vector3f2, vector3f3, vector3f1);
double d = Basic.lengthL2(vector3f1);
if (Numerics.gt(d, 1E-008D))
{
Basic.divScalar(d, vector3f1);
vector3f.set(vector3f1);
}
else
{
vector3f.x = vector3f.y = vector3f.z = 0.0F;
}
vector3f2.set(vector3f3);
k = l;
l = triangulator.fetchNextData(k);
for (int l1 = triangulator.fetchData(l); k != i; l1 = triangulator.fetchData(l))
{
Basic.vectorSub(triangulator.vertices[l1], triangulator.vertices[j1], vector3f3);
Basic.vectorProduct(vector3f2, vector3f3, vector3f1);
d = Basic.lengthL2(vector3f1);
if (Numerics.gt(d, 1E-008D))
{
Basic.divScalar(d, vector3f1);
if (Basic.dotProduct(vector3f, vector3f1) < 0.0D)
Basic.invertVector(vector3f1);
Basic.vectorAdd(vector3f, vector3f1, vector3f);
}
vector3f2.set(vector3f3);
k = l;
l = triangulator.fetchNextData(k);
}
d = Basic.lengthL2(vector3f);
if (Numerics.gt(d, 1E-008D))
{
Basic.divScalar(d, vector3f);
}
else
{
vector3f.x = vector3f.y = 0.0F;
vector3f.z = 1.0F;
}
}
public static void projectPoints(Triangulator triangulator, int i, int j, Vector3f vector3f)
{
Matrix4f matrix4f = new Matrix4f();
Point3f point3f = new Point3f();
Vector3f vector3f1 = new Vector3f();
Vector3f vector3f2 = new Vector3f();
if ((double)Math.Abs(vector3f.x) > 0.10000000000000001D || (double)Math.Abs(vector3f.y) > 0.10000000000000001D)
{
vector3f1.x = -vector3f.y;
vector3f1.y = vector3f.x;
vector3f1.z = 0.0F;
}
else
{
vector3f1.x = vector3f.z;
vector3f1.z = -vector3f.x;
vector3f1.y = 0.0F;
}
double d = Basic.lengthL2(vector3f1);
Basic.divScalar(d, vector3f1);
Basic.vectorProduct(vector3f1, vector3f, vector3f2);
d = Basic.lengthL2(vector3f2);
Basic.divScalar(d, vector3f2);
matrix4f.m00 = vector3f1.x;
matrix4f.m01 = vector3f1.y;
matrix4f.m02 = vector3f1.z;
matrix4f.m03 = 0.0F;
matrix4f.m10 = vector3f2.x;
matrix4f.m11 = vector3f2.y;
matrix4f.m12 = vector3f2.z;
matrix4f.m13 = 0.0F;
matrix4f.m20 = vector3f.x;
matrix4f.m21 = vector3f.y;
matrix4f.m22 = vector3f.z;
matrix4f.m23 = 0.0F;
matrix4f.m30 = 0.0F;
matrix4f.m31 = 0.0F;
matrix4f.m32 = 0.0F;
matrix4f.m33 = 1.0F;
triangulator.initPnts(20);
for (int i1 = i; i1 < j; i1++)
{
int k = triangulator.loops[i1];
int l = k;
int j1 = triangulator.fetchData(l);
matrix4f.transform(triangulator.vertices[j1], point3f);
j1 = triangulator.storePoint(point3f.x, point3f.y);
triangulator.updateIndex(l, j1);
l = triangulator.fetchNextData(l);
for (int k1 = triangulator.fetchData(l); l != k; k1 = triangulator.fetchData(l))
{
matrix4f.transform(triangulator.vertices[k1], point3f);
k1 = triangulator.storePoint(point3f.x, point3f.y);
triangulator.updateIndex(l, k1);
l = triangulator.fetchNextData(l);
}
}
}
}
public class Clean
{
public Clean()
{
}
public static void initPUnsorted(Triangulator triangulator, int i)
{
if(i > triangulator.maxNumPUnsorted)
{
triangulator.maxNumPUnsorted = i;
triangulator.pUnsorted = new Point2f[triangulator.maxNumPUnsorted];
for(int j = 0; j < triangulator.maxNumPUnsorted; j++)
triangulator.pUnsorted[j] = new Point2f();
}
}
public static int cleanPolyhedralFace(Triangulator triangulator, int i, int j)
{
initPUnsorted(triangulator, triangulator.numPoints);
for(int l = 0; l < triangulator.numPoints; l++)
triangulator.pUnsorted[l].set(triangulator.points[l]);
sort(triangulator.points, triangulator.numPoints);
int i1 = 0;
for(int k1 = 1; k1 < triangulator.numPoints; k1++)
if(pComp(triangulator.points[i1], triangulator.points[k1]) != 0)
{
i1++;
triangulator.points[i1] = triangulator.points[k1];
}
int j2 = i1 + 1;
int k = triangulator.numPoints - j2;
for(int j1 = i; j1 < j; j1++)
{
int l2 = triangulator.loops[j1];
int i3 = triangulator.fetchNextData(l2);
int k2;
for(k2 = triangulator.fetchData(i3); i3 != l2; k2 = triangulator.fetchData(i3))
{
int l1 = findPInd(triangulator.points, j2, triangulator.pUnsorted[k2]);
triangulator.updateIndex(i3, l1);
i3 = triangulator.fetchNextData(i3);
}
int i2 = findPInd(triangulator.points, j2, triangulator.pUnsorted[k2]);
triangulator.updateIndex(i3, i2);
}
triangulator.numPoints = j2;
return k;
}
public static void sort(Point2f[] apoint2f, int i)
{
Point2f point2f = new Point2f();
for(int j = 0; j < i; j++)
{
for(int k = j + 1; k < i; k++)
if(pComp(apoint2f[j], apoint2f[k]) > 0)
{
point2f.set(apoint2f[j]);
apoint2f[j].set(apoint2f[k]);
apoint2f[k].set(point2f);
}
}
}
public static int findPInd(Point2f[] apoint2f, int i, Point2f point2f)
{
for(int j = 0; j < i; j++)
if(point2f.x == apoint2f[j].x && point2f.y == apoint2f[j].y)
return j;
return -1;
}
public static int pComp(Point2f point2f, Point2f point2f1)
{
if(point2f.x < point2f1.x)
return -1;
if(point2f.x > point2f1.x)
return 1;
if(point2f.y < point2f1.y)
return -1;
return point2f.y <= point2f1.y ? 0 : 1;
}
}
public class Numerics
{
public Numerics()
{
}
public static double max3(double d, double d1, double d2)
{
return d <= d1 ? d1 <= d2 ? d2 : d1 : d <= d2 ? d2 : d;
}
public static double min3(double d, double d1, double d2)
{
return d >= d1 ? d1 >= d2 ? d2 : d1 : d >= d2 ? d2 : d;
}
public static bool lt(double d, double d1)
{
return d < -d1;
}
public static bool le(double d, double d1)
{
return d <= d1;
}
public static bool ge(double d, double d1)
{
return d > -d1;
}
public static bool eq(double d, double d1)
{
return d <= d1 && d >= -d1;
}
public static bool gt(double d, double d1)
{
return d > d1;
}
public static double baseLength(Tuple2f tuple2f, Tuple2f tuple2f1)
{
double d = tuple2f1.x - tuple2f.x;
double d1 = tuple2f1.y - tuple2f.y;
return Math.Abs(d) + Math.Abs(d1);
}
public static double sideLength(Tuple2f tuple2f, Tuple2f tuple2f1)
{
double d = tuple2f1.x - tuple2f.x;
double d1 = tuple2f1.y - tuple2f.y;
return d * d + d1 * d1;
}
public static bool inBetween(int i, int j, int k)
{
return i <= k && k <= j;
}
public static bool strictlyInBetween(int i, int j, int k)
{
return i < k && k < j;
}
public static double stableDet2D(Triangulator triangulator, int i, int j, int k)
{
double d;
if(i == j || i == k || j == k)
{
d = 0.0D;
} else
{
Point2f point2f = triangulator.points[i];
Point2f point2f1 = triangulator.points[j];
Point2f point2f2 = triangulator.points[k];
if(i < j)
{
if(j < k)
d = Basic.det2D(point2f, point2f1, point2f2);
else
if(i < k)
d = -Basic.det2D(point2f, point2f2, point2f1);
else
d = Basic.det2D(point2f2, point2f, point2f1);
} else
if(i < k)
d = -Basic.det2D(point2f1, point2f, point2f2);
else
if(j < k)
d = Basic.det2D(point2f1, point2f2, point2f);
else
d = -Basic.det2D(point2f2, point2f1, point2f);
}
return d;
}
public static int orientation(Triangulator triangulator, int i, int j, int k)
{
double d = stableDet2D(triangulator, i, j, k);
int byte0;
if (lt(d, triangulator.epsilon))
byte0 = -1;
else
if (gt(d, triangulator.epsilon))
byte0 = 1;
else
byte0 = 0;
return byte0;
}
public static bool isInCone(Triangulator triangulator, int i, int j, int k, int l, bool flag)
{
bool flag1 = true;
if(flag)
{
if(i != j)
{
int i1 = orientation(triangulator, i, j, l);
if(i1 < 0)
flag1 = false;
else
if(i1 == 0)
if(i < j)
{
if(!inBetween(i, j, l))
flag1 = false;
} else
if(!inBetween(j, i, l))
flag1 = false;
}
if(j != k && flag1)
{
int k1 = orientation(triangulator, j, k, l);
if(k1 < 0)
flag1 = false;
else
if(k1 == 0)
if(j < k)
{
if(!inBetween(j, k, l))
flag1 = false;
} else
if(!inBetween(k, j, l))
flag1 = false;
}
} else
{
int j1 = orientation(triangulator, i, j, l);
if(j1 <= 0)
{
int l1 = orientation(triangulator, j, k, l);
if(l1 < 0)
flag1 = false;
}
}
return flag1;
}
public static int isConvexAngle(Triangulator triangulator, int i, int j, int k, int l)
{
if(i == j)
return j != k ? 1 : 1;
if(j == k)
return -1;
int j1 = orientation(triangulator, i, j, k);
int i1;
if(j1 > 0)
i1 = 1;
else
if(j1 < 0)
{
i1 = -1;
} else
{
Point2f point2f = new Point2f();
Point2f point2f1 = new Point2f();
Basic.vectorSub2D(triangulator.points[i], triangulator.points[j], point2f);
Basic.vectorSub2D(triangulator.points[k], triangulator.points[j], point2f1);
double d = Basic.dotProduct2D(point2f, point2f1);
if(d < 0.0D)
i1 = 0;
else
i1 = spikeAngle(triangulator, i, j, k, l);
}
return i1;
}
public static bool pntInTriangle(Triangulator triangulator, int i, int j, int k, int l)
{
bool flag = false;
int i1 = orientation(triangulator, j, k, l);
if(i1 >= 0)
{
int j1 = orientation(triangulator, i, j, l);
if(j1 >= 0)
{
int k1 = orientation(triangulator, k, i, l);
if(k1 >= 0)
flag = true;
}
}
return flag;
}
public static bool vtxInTriangle(Triangulator triangulator, int i, int j, int k, int l, int[] ai)
{
bool flag = false;
int i1 = orientation(triangulator, j, k, l);
if(i1 >= 0)
{
int j1 = orientation(triangulator, i, j, l);
if(j1 > 0)
{
j1 = orientation(triangulator, k, i, l);
if(j1 > 0)
{
flag = true;
ai[0] = 0;
} else
if(j1 == 0)
{
flag = true;
ai[0] = 1;
}
} else
if(j1 == 0)
{
int k1 = orientation(triangulator, k, i, l);
if(k1 > 0)
{