本文整理汇总了C#中TriangleNet.Data.Otri.LnextSelf方法的典型用法代码示例。如果您正苦于以下问题:C# Otri.LnextSelf方法的具体用法?C# Otri.LnextSelf怎么用?C# Otri.LnextSelf使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类TriangleNet.Data.Otri
的用法示例。
在下文中一共展示了Otri.LnextSelf方法的8个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: ScoutSegment
/// <summary>
/// Scout the first triangle on the path from one endpoint to another, and check
/// for completion (reaching the second endpoint), a collinear vertex, or the
/// intersection of two segments.
/// </summary>
/// <param name="searchtri"></param>
/// <param name="endpoint2"></param>
/// <param name="newmark"></param>
/// <returns>Returns true if the entire segment is successfully inserted, and false
/// if the job must be finished by ConstrainedEdge().</returns>
/// <remarks>
/// If the first triangle on the path has the second endpoint as its
/// destination or apex, a subsegment is inserted and the job is done.
///
/// If the first triangle on the path has a destination or apex that lies on
/// the segment, a subsegment is inserted connecting the first endpoint to
/// the collinear vertex, and the search is continued from the collinear
/// vertex.
///
/// If the first triangle on the path has a subsegment opposite its origin,
/// then there is a segment that intersects the segment being inserted.
/// Their intersection vertex is inserted, splitting the subsegment.
/// </remarks>
private bool ScoutSegment(ref Otri searchtri, Vertex endpoint2, int newmark)
{
Otri crosstri = default(Otri);
Osub crosssubseg = default(Osub);
Vertex leftvertex, rightvertex;
FindDirectionResult collinear;
collinear = FindDirection(ref searchtri, endpoint2);
rightvertex = searchtri.Dest();
leftvertex = searchtri.Apex();
if (((leftvertex.x == endpoint2.x) && (leftvertex.y == endpoint2.y)) ||
((rightvertex.x == endpoint2.x) && (rightvertex.y == endpoint2.y)))
{
// The segment is already an edge in the mesh.
if ((leftvertex.x == endpoint2.x) && (leftvertex.y == endpoint2.y))
{
searchtri.LprevSelf();
}
// Insert a subsegment, if there isn't already one there.
InsertSubseg(ref searchtri, newmark);
return true;
}
else if (collinear == FindDirectionResult.Leftcollinear)
{
// We've collided with a vertex between the segment's endpoints.
// Make the collinear vertex be the triangle's origin.
searchtri.LprevSelf();
InsertSubseg(ref searchtri, newmark);
// Insert the remainder of the segment.
return ScoutSegment(ref searchtri, endpoint2, newmark);
}
else if (collinear == FindDirectionResult.Rightcollinear)
{
// We've collided with a vertex between the segment's endpoints.
InsertSubseg(ref searchtri, newmark);
// Make the collinear vertex be the triangle's origin.
searchtri.LnextSelf();
// Insert the remainder of the segment.
return ScoutSegment(ref searchtri, endpoint2, newmark);
}
else
{
searchtri.Lnext(ref crosstri);
crosstri.SegPivot(ref crosssubseg);
// Check for a crossing segment.
if (crosssubseg.seg == Mesh.dummysub)
{
return false;
}
else
{
// Insert a vertex at the intersection.
SegmentIntersection(ref crosstri, ref crosssubseg, endpoint2);
crosstri.Copy(ref searchtri);
InsertSubseg(ref searchtri, newmark);
// Insert the remainder of the segment.
return ScoutSegment(ref searchtri, endpoint2, newmark);
}
}
}
示例2: PreciseLocate
//.........这里部分代码省略.........
Vertex forg, fdest, fapex;
float orgorient, destorient;
bool moveleft;
// Where are we?
forg = searchtri.Org();
fdest = searchtri.Dest();
fapex = searchtri.Apex();
while (true)
{
// Check whether the apex is the point we seek.
if ((fapex.x == searchpoint.X) && (fapex.y == searchpoint.Y))
{
searchtri.LprevSelf();
return LocateResult.OnVertex;
}
// Does the point lie on the other side of the line defined by the
// triangle edge opposite the triangle's destination?
destorient = Primitives.CounterClockwise(forg, fapex, searchpoint);
// Does the point lie on the other side of the line defined by the
// triangle edge opposite the triangle's origin?
orgorient = Primitives.CounterClockwise(fapex, fdest, searchpoint);
if (destorient > 0.0)
{
if (orgorient > 0.0)
{
// Move left if the inner product of (fapex - searchpoint) and
// (fdest - forg) is positive. This is equivalent to drawing
// a line perpendicular to the line (forg, fdest) and passing
// through 'fapex', and determining which side of this line
// 'searchpoint' falls on.
moveleft = (fapex.x - searchpoint.X) * (fdest.x - forg.x) +
(fapex.y - searchpoint.Y) * (fdest.y - forg.y) > 0.0;
}
else
{
moveleft = true;
}
}
else
{
if (orgorient > 0.0)
{
moveleft = false;
}
else
{
// The point we seek must be on the boundary of or inside this
// triangle.
if (destorient == 0.0)
{
searchtri.LprevSelf();
return LocateResult.OnEdge;
}
if (orgorient == 0.0)
{
searchtri.LnextSelf();
return LocateResult.OnEdge;
}
return LocateResult.InTriangle;
}
}
// Move to another triangle. Leave a trace 'backtracktri' in case
// floating-point roundoff or some such bogey causes us to walk
// off a boundary of the triangulation.
if (moveleft)
{
searchtri.Lprev(ref backtracktri);
fdest = fapex;
}
else
{
searchtri.Lnext(ref backtracktri);
forg = fapex;
}
backtracktri.Sym(ref searchtri);
if (mesh.checksegments && stopatsubsegment)
{
// Check for walking through a subsegment.
backtracktri.SegPivot(ref checkedge);
if (checkedge.seg != Mesh.dummysub)
{
// Go back to the last triangle.
backtracktri.Copy(ref searchtri);
return LocateResult.Outside;
}
}
// Check for walking right out of the triangulation.
if (searchtri.triangle == Mesh.dummytri)
{
// Go back to the last triangle.
backtracktri.Copy(ref searchtri);
return LocateResult.Outside;
}
fapex = searchtri.Apex();
}
}
示例3: Locate
//.........这里部分代码省略.........
/// Returns INTRIANGLE if the point lies strictly within a triangle.
/// 'searchtri' is a handle on the triangle that contains the point.
///
/// Returns OUTSIDE if the point lies outside the mesh. 'searchtri' is a
/// handle whose primary edge the point is to the right of. This might
/// occur when the circumcenter of a triangle falls just slightly outside
/// the mesh due to floating-point roundoff error. It also occurs when
/// seeking a hole or region point that a foolish user has placed outside
/// the mesh.
///
/// WARNING: This routine is designed for convex triangulations, and will
/// not generally work after the holes and concavities have been carved.
/// </remarks>
public LocateResult Locate(Point searchpoint, ref Otri searchtri)
{
Otri sampletri = default(Otri);
Vertex torg, tdest;
float searchdist, dist;
float ahead;
// Record the distance from the suggested starting triangle to the
// point we seek.
torg = searchtri.Org();
searchdist = (searchpoint.X - torg.x) * (searchpoint.X - torg.x) +
(searchpoint.Y - torg.y) * (searchpoint.Y - torg.y);
// If a recently encountered triangle has been recorded and has not been
// deallocated, test it as a good starting point.
if (recenttri.triangle != null)
{
if (!Otri.IsDead(recenttri.triangle))
{
torg = recenttri.Org();
if ((torg.x == searchpoint.X) && (torg.y == searchpoint.Y))
{
recenttri.Copy(ref searchtri);
return LocateResult.OnVertex;
}
dist = (searchpoint.X - torg.x) * (searchpoint.X - torg.x) +
(searchpoint.Y - torg.y) * (searchpoint.Y - torg.y);
if (dist < searchdist)
{
recenttri.Copy(ref searchtri);
searchdist = dist;
}
}
}
// TODO: Improve sampling.
sampler.Update(mesh);
int[] samples = sampler.GetSamples(mesh);
foreach (var key in samples)
{
sampletri.triangle = mesh.triangles[key];
if (!Otri.IsDead(sampletri.triangle))
{
torg = sampletri.Org();
dist = (searchpoint.X - torg.x) * (searchpoint.X - torg.x) +
(searchpoint.Y - torg.y) * (searchpoint.Y - torg.y);
if (dist < searchdist)
{
sampletri.Copy(ref searchtri);
searchdist = dist;
}
}
}
// Where are we?
torg = searchtri.Org();
tdest = searchtri.Dest();
// Check the starting triangle's vertices.
if ((torg.x == searchpoint.X) && (torg.y == searchpoint.Y))
{
return LocateResult.OnVertex;
}
if ((tdest.x == searchpoint.X) && (tdest.y == searchpoint.Y))
{
searchtri.LnextSelf();
return LocateResult.OnVertex;
}
// Orient 'searchtri' to fit the preconditions of calling preciselocate().
ahead = Primitives.CounterClockwise(torg, tdest, searchpoint);
if (ahead < 0.0)
{
// Turn around so that 'searchpoint' is to the left of the
// edge specified by 'searchtri'.
searchtri.SymSelf();
}
else if (ahead == 0.0)
{
// Check if 'searchpoint' is between 'torg' and 'tdest'.
if (((torg.x < searchpoint.X) == (searchpoint.X < tdest.x)) &&
((torg.y < searchpoint.Y) == (searchpoint.Y < tdest.y)))
{
return LocateResult.OnEdge;
}
}
return PreciseLocate(searchpoint, ref searchtri, false);
}
示例4: FindNewLocation
//.........这里部分代码省略.........
// obtuse
isObtuse = true;
}
else if (Math.Abs(cosMaxAngle - 0.0) <= EPS)
{
// right triangle (largest angle is 90 degrees)
isObtuse = true;
}
else
{
// nonobtuse
isObtuse = false;
}
/// RELOCATION (LOCAL SMOOTHING) ///
/// check for possible relocation of one of triangle's points ///
relocated = DoSmoothing(delotri, torg, tdest, tapex, ref newloc);
/// if relocation is possible, delete that vertex and insert a vertex at the new location ///
if (relocated > 0)
{
Statistic.RelocationCount++;
dx = newloc[0] - torg.x;
dy = newloc[1] - torg.y;
origin_x = torg.x; // keep for later use
origin_y = torg.y;
switch (relocated)
{
case 1:
//printf("Relocate: (%f,%f)\n", torg[0],torg[1]);
mesh.DeleteVertex(ref delotri);
break;
case 2:
//printf("Relocate: (%f,%f)\n", tdest[0],tdest[1]);
delotri.LnextSelf();
mesh.DeleteVertex(ref delotri);
break;
case 3:
//printf("Relocate: (%f,%f)\n", tapex[0],tapex[1]);
delotri.LprevSelf();
mesh.DeleteVertex(ref delotri);
break;
}
}
else
{
// calculate radius of the petal according to angle constraint
// first find the visible region, PETAL
// find the center of the circle and radius
// choose minimum angle as the maximum of quality angle and the minimum angle of the bad triangle
minangle = Math.Acos((middleEdgeDist + longestEdgeDist - shortestEdgeDist) / (2 * Math.Sqrt(middleEdgeDist) * Math.Sqrt(longestEdgeDist))) * 180.0 / Math.PI;
if (behavior.MinAngle > minangle)
{
minangle = behavior.MinAngle;
}
else
{
minangle = minangle + 0.5;
}
petalRadius = Math.Sqrt(shortestEdgeDist) / (2 * Math.Sin(minangle * Math.PI / 180.0));
/// compute two possible centers of the petal ///
// finding the center
// first find the middle point of smallest edge
xMidOfShortestEdge = (middleAngleCorner.x + largestAngleCorner.x) / 2.0;
yMidOfShortestEdge = (middleAngleCorner.y + largestAngleCorner.y) / 2.0;
// two possible centers
xPetalCtr_1 = xMidOfShortestEdge + Math.Sqrt(petalRadius * petalRadius - (shortestEdgeDist / 4)) * (middleAngleCorner.y -
示例5: MinDistanceToNeighbor
/// <summary>
/// Given the triangulation, and a vertex returns the minimum distance to the
/// vertices of the triangle where the given vertex located.
/// </summary>
/// <param name="newlocX"></param>
/// <param name="newlocY"></param>
/// <param name="searchtri"></param>
/// <returns></returns>
private double MinDistanceToNeighbor(double newlocX, double newlocY, ref Otri searchtri)
{
Otri horiz = default(Otri); // for search operation
LocateResult intersect = LocateResult.Outside;
Vertex v1, v2, v3, torg, tdest;
double d1, d2, d3, ahead;
//triangle ptr; // Temporary variable used by sym().
Point newvertex = new Point(newlocX, newlocY);
// printf("newvertex %f,%f\n", newvertex[0], newvertex[1]);
// Find the location of the vertex to be inserted. Check if a good
// starting triangle has already been provided by the caller.
// Find a boundary triangle.
//horiz.tri = m.dummytri;
//horiz.orient = 0;
//horiz.symself();
// Search for a triangle containing 'newvertex'.
// Start searching from the triangle provided by the caller.
// Where are we?
torg = searchtri.Org();
tdest = searchtri.Dest();
// Check the starting triangle's vertices.
if ((torg.x == newvertex.x) && (torg.y == newvertex.y))
{
intersect = LocateResult.OnVertex;
searchtri.Copy(ref horiz);
}
else if ((tdest.x == newvertex.x) && (tdest.y == newvertex.y))
{
searchtri.LnextSelf();
intersect = LocateResult.OnVertex;
searchtri.Copy(ref horiz);
}
else
{
// Orient 'searchtri' to fit the preconditions of calling preciselocate().
ahead = Primitives.CounterClockwise(torg, tdest, newvertex);
if (ahead < 0.0)
{
// Turn around so that 'searchpoint' is to the left of the
// edge specified by 'searchtri'.
searchtri.SymSelf();
searchtri.Copy(ref horiz);
intersect = mesh.locator.PreciseLocate(newvertex, ref horiz, false);
}
else if (ahead == 0.0)
{
// Check if 'searchpoint' is between 'torg' and 'tdest'.
if (((torg.x < newvertex.x) == (newvertex.x < tdest.x)) &&
((torg.y < newvertex.y) == (newvertex.y < tdest.y)))
{
intersect = LocateResult.OnEdge;
searchtri.Copy(ref horiz);
}
}
else
{
searchtri.Copy(ref horiz);
intersect = mesh.locator.PreciseLocate(newvertex, ref horiz, false);
}
}
if (intersect == LocateResult.OnVertex || intersect == LocateResult.Outside)
{
// set distance to 0
//m.VertexDealloc(newvertex);
return 0.0;
}
else
{ // intersect == ONEDGE || intersect == INTRIANGLE
// find the triangle vertices
v1 = horiz.Org();
v2 = horiz.Dest();
v3 = horiz.Apex();
d1 = (v1.x - newvertex.x) * (v1.x - newvertex.x) + (v1.y - newvertex.y) * (v1.y - newvertex.y);
d2 = (v2.x - newvertex.x) * (v2.x - newvertex.x) + (v2.y - newvertex.y) * (v2.y - newvertex.y);
d3 = (v3.x - newvertex.x) * (v3.x - newvertex.x) + (v3.y - newvertex.y) * (v3.y - newvertex.y);
//m.VertexDealloc(newvertex);
// find minimum of the distance
if (d1 <= d2 && d1 <= d3)
{
return d1;
}
else if (d2 <= d3)
{
return d2;
}
else
{
return d3;
//.........这里部分代码省略.........
示例6: DivconqRecurse
/// <summary>
/// Recursively form a Delaunay triangulation by the divide-and-conquer method.
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <param name="axis"></param>
/// <param name="farleft"></param>
/// <param name="farright"></param>
/// <remarks>
/// Recursively breaks down the problem into smaller pieces, which are
/// knitted together by mergehulls(). The base cases (problems of two or
/// three vertices) are handled specially here.
///
/// On completion, 'farleft' and 'farright' are bounding triangles such that
/// the origin of 'farleft' is the leftmost vertex (breaking ties by
/// choosing the highest leftmost vertex), and the destination of
/// 'farright' is the rightmost vertex (breaking ties by choosing the
/// lowest rightmost vertex).
/// </remarks>
void DivconqRecurse(int left, int right, int axis,
ref Otri farleft, ref Otri farright)
{
Otri midtri = default(Otri);
Otri tri1 = default(Otri);
Otri tri2 = default(Otri);
Otri tri3 = default(Otri);
Otri innerleft = default(Otri), innerright = default(Otri);
double area;
int vertices = right - left + 1;
int divider;
if (vertices == 2)
{
// The triangulation of two vertices is an edge. An edge is
// represented by two bounding triangles.
mesh.MakeTriangle(ref farleft);
farleft.SetOrg(sortarray[left]);
farleft.SetDest(sortarray[left + 1]);
// The apex is intentionally left NULL.
mesh.MakeTriangle(ref farright);
farright.SetOrg(sortarray[left + 1]);
farright.SetDest(sortarray[left]);
// The apex is intentionally left NULL.
farleft.Bond(ref farright);
farleft.LprevSelf();
farright.LnextSelf();
farleft.Bond(ref farright);
farleft.LprevSelf();
farright.LnextSelf();
farleft.Bond(ref farright);
// Ensure that the origin of 'farleft' is sortarray[0].
farright.Lprev(ref farleft);
return;
}
else if (vertices == 3)
{
// The triangulation of three vertices is either a triangle (with
// three bounding triangles) or two edges (with four bounding
// triangles). In either case, four triangles are created.
mesh.MakeTriangle(ref midtri);
mesh.MakeTriangle(ref tri1);
mesh.MakeTriangle(ref tri2);
mesh.MakeTriangle(ref tri3);
area = Primitives.CounterClockwise(sortarray[left], sortarray[left + 1], sortarray[left + 2]);
if (area == 0.0)
{
// Three collinear vertices; the triangulation is two edges.
midtri.SetOrg(sortarray[left]);
midtri.SetDest(sortarray[left + 1]);
tri1.SetOrg(sortarray[left + 1]);
tri1.SetDest(sortarray[left]);
tri2.SetOrg(sortarray[left + 2]);
tri2.SetDest(sortarray[left + 1]);
tri3.SetOrg(sortarray[left + 1]);
tri3.SetDest(sortarray[left + 2]);
// All apices are intentionally left NULL.
midtri.Bond(ref tri1);
tri2.Bond(ref tri3);
midtri.LnextSelf();
tri1.LprevSelf();
tri2.LnextSelf();
tri3.LprevSelf();
midtri.Bond(ref tri3);
tri1.Bond(ref tri2);
midtri.LnextSelf();
tri1.LprevSelf();
tri2.LnextSelf();
tri3.LprevSelf();
midtri.Bond(ref tri1);
tri2.Bond(ref tri3);
// Ensure that the origin of 'farleft' is sortarray[0].
tri1.Copy(ref farleft);
// Ensure that the destination of 'farright' is sortarray[2].
tri2.Copy(ref farright);
}
else
{
// The three vertices are not collinear; the triangulation is one
// triangle, namely 'midtri'.
//.........这里部分代码省略.........
示例7: MergeHulls
/// <summary>
/// Merge two adjacent Delaunay triangulations into a single Delaunay triangulation.
/// </summary>
/// <param name="farleft">Bounding triangles of the left triangulation.</param>
/// <param name="innerleft">Bounding triangles of the left triangulation.</param>
/// <param name="innerright">Bounding triangles of the right triangulation.</param>
/// <param name="farright">Bounding triangles of the right triangulation.</param>
/// <param name="axis"></param>
/// <remarks>
/// This is similar to the algorithm given by Guibas and Stolfi, but uses
/// a triangle-based, rather than edge-based, data structure.
///
/// The algorithm walks up the gap between the two triangulations, knitting
/// them together. As they are merged, some of their bounding triangles
/// are converted into real triangles of the triangulation. The procedure
/// pulls each hull's bounding triangles apart, then knits them together
/// like the teeth of two gears. The Delaunay property determines, at each
/// step, whether the next "tooth" is a bounding triangle of the left hull
/// or the right. When a bounding triangle becomes real, its apex is
/// changed from NULL to a real vertex.
///
/// Only two new triangles need to be allocated. These become new bounding
/// triangles at the top and bottom of the seam. They are used to connect
/// the remaining bounding triangles (those that have not been converted
/// into real triangles) into a single fan.
///
/// On entry, 'farleft' and 'innerleft' are bounding triangles of the left
/// triangulation. The origin of 'farleft' is the leftmost vertex, and
/// the destination of 'innerleft' is the rightmost vertex of the
/// triangulation. Similarly, 'innerright' and 'farright' are bounding
/// triangles of the right triangulation. The origin of 'innerright' and
/// destination of 'farright' are the leftmost and rightmost vertices.
///
/// On completion, the origin of 'farleft' is the leftmost vertex of the
/// merged triangulation, and the destination of 'farright' is the rightmost
/// vertex.
/// </remarks>
void MergeHulls(ref Otri farleft, ref Otri innerleft, ref Otri innerright,
ref Otri farright, int axis)
{
Otri leftcand = default(Otri), rightcand = default(Otri);
Otri nextedge = default(Otri);
Otri sidecasing = default(Otri), topcasing = default(Otri), outercasing = default(Otri);
Otri checkedge = default(Otri);
Otri baseedge = default(Otri);
Vertex innerleftdest;
Vertex innerrightorg;
Vertex innerleftapex, innerrightapex;
Vertex farleftpt, farrightpt;
Vertex farleftapex, farrightapex;
Vertex lowerleft, lowerright;
Vertex upperleft, upperright;
Vertex nextapex;
Vertex checkvertex;
bool changemade;
bool badedge;
bool leftfinished, rightfinished;
innerleftdest = innerleft.Dest();
innerleftapex = innerleft.Apex();
innerrightorg = innerright.Org();
innerrightapex = innerright.Apex();
// Special treatment for horizontal cuts.
if (useDwyer && (axis == 1))
{
farleftpt = farleft.Org();
farleftapex = farleft.Apex();
farrightpt = farright.Dest();
farrightapex = farright.Apex();
// The pointers to the extremal vertices are shifted to point to the
// topmost and bottommost vertex of each hull, rather than the
// leftmost and rightmost vertices.
while (farleftapex.y < farleftpt.y)
{
farleft.LnextSelf();
farleft.SymSelf();
farleftpt = farleftapex;
farleftapex = farleft.Apex();
}
innerleft.Sym(ref checkedge);
checkvertex = checkedge.Apex();
while (checkvertex.y > innerleftdest.y)
{
checkedge.Lnext(ref innerleft);
innerleftapex = innerleftdest;
innerleftdest = checkvertex;
innerleft.Sym(ref checkedge);
checkvertex = checkedge.Apex();
}
while (innerrightapex.y < innerrightorg.y)
{
innerright.LnextSelf();
innerright.SymSelf();
innerrightorg = innerrightapex;
innerrightapex = innerright.Apex();
}
farright.Sym(ref checkedge);
checkvertex = checkedge.Apex();
while (checkvertex.y > farrightpt.y)
{
//.........这里部分代码省略.........
示例8: FindNewLocationWithoutMaxAngle
//.........这里部分代码省略.........
// obtuse
isObtuse = true;
}
else if (UnityEngine.Mathf.Abs(cosMaxAngle - 0.0f) <= UnityEngine.Mathf.Epsilon)
{
// right triangle (largest angle is 90 degrees)
isObtuse = true;
}
else
{
// nonobtuse
isObtuse = false;
}
/// RELOCATION (LOCAL SMOOTHING) ///
/// check for possible relocation of one of triangle's points ///
relocated = DoSmoothing(delotri, torg, tdest, tapex, ref newloc);
/// if relocation is possible, delete that vertex and insert a vertex at the new location ///
if (relocated > 0)
{
Statistic.RelocationCount++;
dx = newloc[0] - torg.x;
dy = newloc[1] - torg.y;
origin_x = torg.x; // keep for later use
origin_y = torg.y;
switch (relocated)
{
case 1:
//printf("Relocate: (%f,%f)\n", torg[0],torg[1]);
mesh.DeleteVertex(ref delotri);
break;
case 2:
//printf("Relocate: (%f,%f)\n", tdest[0],tdest[1]);
delotri.LnextSelf();
mesh.DeleteVertex(ref delotri);
break;
case 3:
//printf("Relocate: (%f,%f)\n", tapex[0],tapex[1]);
delotri.LprevSelf();
mesh.DeleteVertex(ref delotri);
break;
}
}
else
{
// calculate radius of the petal according to angle constraint
// first find the visible region, PETAL
// find the center of the circle and radius
petalRadius = UnityEngine.Mathf.Sqrt(shortestEdgeDist) / (2f * UnityEngine.Mathf.Sin(behavior.MinAngle * UnityEngine.Mathf.PI / 180.0f));
/// compute two possible centers of the petal ///
// finding the center
// first find the middle point of smallest edge
xMidOfShortestEdge = (middleAngleCorner.x + largestAngleCorner.x) / 2.0f;
yMidOfShortestEdge = (middleAngleCorner.y + largestAngleCorner.y) / 2.0f;
// two possible centers
xPetalCtr_1 = xMidOfShortestEdge + UnityEngine.Mathf.Sqrt(petalRadius * petalRadius - (shortestEdgeDist / 4)) * (middleAngleCorner.y -
largestAngleCorner.y) / UnityEngine.Mathf.Sqrt(shortestEdgeDist);
yPetalCtr_1 = yMidOfShortestEdge + UnityEngine.Mathf.Sqrt(petalRadius * petalRadius - (shortestEdgeDist / 4)) * (largestAngleCorner.x -
middleAngleCorner.x) / UnityEngine.Mathf.Sqrt(shortestEdgeDist);
xPetalCtr_2 = xMidOfShortestEdge - UnityEngine.Mathf.Sqrt(petalRadius * petalRadius - (shortestEdgeDist / 4)) * (middleAngleCorner.y -
largestAngleCorner.y) / UnityEngine.Mathf.Sqrt(shortestEdgeDist);
yPetalCtr_2 = yMidOfShortestEdge - UnityEngine.Mathf.Sqrt(petalRadius * petalRadius - (shortestEdgeDist / 4)) * (largestAngleCorner.x -
middleAngleCorner.x) / UnityEngine.Mathf.Sqrt(shortestEdgeDist);
// find the correct circle since there will be two possible circles