本文整理汇总了C#中TriangleNet.Data.Otri.LprevSelf方法的典型用法代码示例。如果您正苦于以下问题:C# Otri.LprevSelf方法的具体用法?C# Otri.LprevSelf怎么用?C# Otri.LprevSelf使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类TriangleNet.Data.Otri
的用法示例。
在下文中一共展示了Otri.LprevSelf方法的7个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: DelaunayFixup
/// <summary>
/// Enforce the Delaunay condition at an edge, fanning out recursively from
/// an existing vertex. Pay special attention to stacking inverted triangles.
/// </summary>
/// <param name="fixuptri"></param>
/// <param name="leftside">Indicates whether or not fixuptri is to the left of
/// the segment being inserted. (Imagine that the segment is pointing up from
/// endpoint1 to endpoint2.)</param>
/// <remarks>
/// This is a support routine for inserting segments into a constrained
/// Delaunay triangulation.
///
/// The origin of fixuptri is treated as if it has just been inserted, and
/// the local Delaunay condition needs to be enforced. It is only enforced
/// in one sector, however, that being the angular range defined by
/// fixuptri.
///
/// This routine also needs to make decisions regarding the "stacking" of
/// triangles. (Read the description of ConstrainedEdge() below before
/// reading on here, so you understand the algorithm.) If the position of
/// the new vertex (the origin of fixuptri) indicates that the vertex before
/// it on the polygon is a reflex vertex, then "stack" the triangle by
/// doing nothing. (fixuptri is an inverted triangle, which is how stacked
/// triangles are identified.)
///
/// Otherwise, check whether the vertex before that was a reflex vertex.
/// If so, perform an edge flip, thereby eliminating an inverted triangle
/// (popping it off the stack). The edge flip may result in the creation
/// of a new inverted triangle, depending on whether or not the new vertex
/// is visible to the vertex three edges behind on the polygon.
///
/// If neither of the two vertices behind the new vertex are reflex
/// vertices, fixuptri and fartri, the triangle opposite it, are not
/// inverted; hence, ensure that the edge between them is locally Delaunay.
/// </remarks>
private void DelaunayFixup(ref Otri fixuptri, bool leftside)
{
Otri neartri = default(Otri);
Otri fartri = default(Otri);
Osub faredge = default(Osub);
Vertex nearvertex, leftvertex, rightvertex, farvertex;
fixuptri.Lnext(ref neartri);
neartri.Sym(ref fartri);
// Check if the edge opposite the origin of fixuptri can be flipped.
if (fartri.triangle == Mesh.dummytri)
{
return;
}
neartri.SegPivot(ref faredge);
if (faredge.seg != Mesh.dummysub)
{
return;
}
// Find all the relevant vertices.
nearvertex = neartri.Apex();
leftvertex = neartri.Org();
rightvertex = neartri.Dest();
farvertex = fartri.Apex();
// Check whether the previous polygon vertex is a reflex vertex.
if (leftside)
{
if (Primitives.CounterClockwise(nearvertex, leftvertex, farvertex) <= 0.0)
{
// leftvertex is a reflex vertex too. Nothing can
// be done until a convex section is found.
return;
}
}
else
{
if (Primitives.CounterClockwise(farvertex, rightvertex, nearvertex) <= 0.0)
{
// rightvertex is a reflex vertex too. Nothing can
// be done until a convex section is found.
return;
}
}
if (Primitives.CounterClockwise(rightvertex, leftvertex, farvertex) > 0.0)
{
// fartri is not an inverted triangle, and farvertex is not a reflex
// vertex. As there are no reflex vertices, fixuptri isn't an
// inverted triangle, either. Hence, test the edge between the
// triangles to ensure it is locally Delaunay.
if (Primitives.InCircle(leftvertex, farvertex, rightvertex, nearvertex) <= 0.0)
{
return;
}
// Not locally Delaunay; go on to an edge flip.
}
// else fartri is inverted; remove it from the stack by flipping.
Flip(ref neartri);
fixuptri.LprevSelf(); // Restore the origin of fixuptri after the flip.
// Recursively process the two triangles that result from the flip.
DelaunayFixup(ref fixuptri, leftside);
DelaunayFixup(ref fartri, leftside);
}
示例2: 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);
}
}
}
示例3: PreciseLocate
/// <summary>
/// Find a triangle or edge containing a given point.
/// </summary>
/// <param name="searchpoint">The point to locate.</param>
/// <param name="searchtri">The triangle to start the search at.</param>
/// <param name="stopatsubsegment"> If 'stopatsubsegment' is set, the search
/// will stop if it tries to walk through a subsegment, and will return OUTSIDE.</param>
/// <returns>Location information.</returns>
/// <remarks>
/// Begins its search from 'searchtri'. It is important that 'searchtri'
/// be a handle with the property that 'searchpoint' is strictly to the left
/// of the edge denoted by 'searchtri', or is collinear with that edge and
/// does not intersect that edge. (In particular, 'searchpoint' should not
/// be the origin or destination of that edge.)
///
/// These conditions are imposed because preciselocate() is normally used in
/// one of two situations:
///
/// (1) To try to find the location to insert a new point. Normally, we
/// know an edge that the point is strictly to the left of. In the
/// incremental Delaunay algorithm, that edge is a bounding box edge.
/// In Ruppert's Delaunay refinement algorithm for quality meshing,
/// that edge is the shortest edge of the triangle whose circumcenter
/// is being inserted.
///
/// (2) To try to find an existing point. In this case, any edge on the
/// convex hull is a good starting edge. You must screen out the
/// possibility that the vertex sought is an endpoint of the starting
/// edge before you call preciselocate().
///
/// On completion, 'searchtri' is a triangle that contains 'searchpoint'.
///
/// This implementation differs from that given by Guibas and Stolfi. It
/// walks from triangle to triangle, crossing an edge only if 'searchpoint'
/// is on the other side of the line containing that edge. After entering
/// a triangle, there are two edges by which one can leave that triangle.
/// If both edges are valid ('searchpoint' is on the other side of both
/// edges), one of the two is chosen by drawing a line perpendicular to
/// the entry edge (whose endpoints are 'forg' and 'fdest') passing through
/// 'fapex'. Depending on which side of this perpendicular 'searchpoint'
/// falls on, an exit edge is chosen.
///
/// This implementation is empirically faster than the Guibas and Stolfi
/// point location routine (which I originally used), which tends to spiral
/// in toward its target.
///
/// Returns ONVERTEX if the point lies on an existing vertex. 'searchtri'
/// is a handle whose origin is the existing vertex.
///
/// Returns ONEDGE if the point lies on a mesh edge. 'searchtri' is a
/// handle whose primary edge is the edge on which the point lies.
///
/// 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.
/// However, it can still be used to find the circumcenter of a triangle, as
/// long as the search is begun from the triangle in question.</remarks>
public LocateResult PreciseLocate(Point searchpoint, ref Otri searchtri,
bool stopatsubsegment)
{
Otri backtracktri = default(Otri);
Osub checkedge = default(Osub);
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
//.........这里部分代码省略.........
示例4: FindNewLocation
//.........这里部分代码省略.........
// 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 -
largestAngleCorner.y) / Math.Sqrt(shortestEdgeDist);
yPetalCtr_1 = yMidOfShortestEdge + Math.Sqrt(petalRadius * petalRadius - (shortestEdgeDist / 4)) * (largestAngleCorner.x -
middleAngleCorner.x) / Math.Sqrt(shortestEdgeDist);
xPetalCtr_2 = xMidOfShortestEdge - Math.Sqrt(petalRadius * petalRadius - (shortestEdgeDist / 4)) * (middleAngleCorner.y -
示例5: 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'.
//.........这里部分代码省略.........
示例6: MergeHulls
//.........这里部分代码省略.........
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)
{
checkedge.Lnext(ref farright);
farrightapex = farrightpt;
farrightpt = checkvertex;
farright.Sym(ref checkedge);
checkvertex = checkedge.Apex();
}
}
// Find a line tangent to and below both hulls.
do
{
changemade = false;
// Make innerleftdest the "bottommost" vertex of the left hull.
if (Primitives.CounterClockwise(innerleftdest, innerleftapex, innerrightorg) > 0.0)
{
innerleft.LprevSelf();
innerleft.SymSelf();
innerleftdest = innerleftapex;
innerleftapex = innerleft.Apex();
changemade = true;
}
// Make innerrightorg the "bottommost" vertex of the right hull.
if (Primitives.CounterClockwise(innerrightapex, innerrightorg, innerleftdest) > 0.0)
{
innerright.LnextSelf();
innerright.SymSelf();
innerrightorg = innerrightapex;
innerrightapex = innerright.Apex();
changemade = true;
}
} while (changemade);
// Find the two candidates to be the next "gear tooth."
innerleft.Sym(ref leftcand);
innerright.Sym(ref rightcand);
// Create the bottom new bounding triangle.
mesh.MakeTriangle(ref baseedge);
// Connect it to the bounding boxes of the left and right triangulations.
baseedge.Bond(ref innerleft);
baseedge.LnextSelf();
baseedge.Bond(ref innerright);
baseedge.LnextSelf();
baseedge.SetOrg(innerrightorg);
baseedge.SetDest(innerleftdest);
// Apex is intentionally left NULL.
// Fix the extreme triangles if necessary.
farleftpt = farleft.Org();
示例7: FindNewLocationWithoutMaxAngle
//.........这里部分代码省略.........
// 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
// calculate the distance to smallest angle corner
dxcenter1 = (xPetalCtr_1 - smallestAngleCorner.x) * (xPetalCtr_1 - smallestAngleCorner.x);
dycenter1 = (yPetalCtr_1 - smallestAngleCorner.y) * (yPetalCtr_1 - smallestAngleCorner.y);
dxcenter2 = (xPetalCtr_2 - smallestAngleCorner.x) * (xPetalCtr_2 - smallestAngleCorner.x);
dycenter2 = (yPetalCtr_2 - smallestAngleCorner.y) * (yPetalCtr_2 - smallestAngleCorner.y);