#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "zlassert.h"
#include "sampleCompTop.h"
#include "sampleCompRight.h"
#define max(a,b) ((a>b)? a:b)
void findTopLeftSegment(vertexArray* leftChain,
Int leftStart,
Int leftEnd,
Real u,
Int& ret_index_small,
Int& ret_index_large
)
{
Int i;
assert(leftStart <= leftEnd);
for(i=leftEnd; i>= leftStart; i--)
{
if(leftChain->getVertex(i)[0] >= u)
break;
}
ret_index_large = i;
if(ret_index_large >= leftStart)
{
for(i=ret_index_large; i>leftStart; i--)
{
if(leftChain->getVertex(i-1)[0] <= leftChain->getVertex(i)[0])
break;
}
ret_index_small = i;
}
}
void findTopRightSegment(vertexArray* rightChain,
Int rightStart,
Int rightEnd,
Real u,
Int& ret_index_small,
Int& ret_index_large)
{
Int i;
assert(rightStart<=rightEnd);
for(i=rightEnd; i>=rightStart; i--)
{
if(rightChain->getVertex(i)[0] <= u)
break;
}
ret_index_large = i;
if(ret_index_large >= rightStart)
{
for(i=ret_index_large; i>rightStart;i--)
{
if(rightChain->getVertex(i-1)[0] >= rightChain->getVertex(i)[0])
break;
}
ret_index_small = i;
}
}
void sampleTopRightWithGridLinePost(Real* topVertex,
vertexArray* rightChain,
Int rightStart,
Int segIndexSmall,
Int segIndexLarge,
Int rightEnd,
gridWrap* grid,
Int gridV,
Int leftU,
Int rightU,
primStream* pStream)
{
if(segIndexLarge < rightEnd)
{
Real *tempTop;
if(segIndexLarge >= rightStart)
tempTop = rightChain->getVertex(segIndexLarge);
else
tempTop = topVertex;
Real tempBot[2];
tempBot[0] = grid->get_u_value(rightU);
tempBot[1] = grid->get_v_value(gridV);
monoTriangulationRecGenOpt(tempTop, tempBot,
NULL, 1,0,
rightChain, segIndexLarge+1, rightEnd,
pStream);
}
if(segIndexLarge >= rightStart)
{
stripOfFanRight(rightChain, segIndexLarge, segIndexSmall, grid, gridV, leftU, rightU, pStream, 0);
Real tempBot[2];
tempBot[0] = grid->get_u_value(leftU);
tempBot[1] = grid->get_v_value(gridV);
monoTriangulation2(topVertex, tempBot, rightChain, rightStart, segIndexSmall, 0, pStream);
}
else grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
}
void sampleTopRightWithGridLine(Real* topVertex,
vertexArray* rightChain,
Int rightStart,
Int rightEnd,
gridWrap* grid,
Int gridV,
Int leftU,
Int rightU,
primStream* pStream
)
{
if(rightEnd < rightStart){
grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
return;
}
Int segIndexSmall, segIndexLarge;
findTopRightSegment(rightChain,
rightStart,
rightEnd,
grid->get_u_value(rightU),
segIndexSmall,
segIndexLarge
);
sampleTopRightWithGridLinePost(topVertex, rightChain,
rightStart,
segIndexSmall,
segIndexLarge,
rightEnd,
grid,
gridV,
leftU,
rightU,
pStream);
}
void sampleTopLeftWithGridLinePost(Real* topVertex,
vertexArray* leftChain,
Int leftStart,
Int segIndexSmall,
Int segIndexLarge,
Int leftEnd,
gridWrap* grid,
Int gridV,
Int leftU,
Int rightU,
primStream* pStream)
{
if(segIndexLarge < leftEnd)
{
Real *tempTop;
if(segIndexLarge >= leftStart)
tempTop = leftChain->getVertex(segIndexLarge);
else
tempTop = topVertex;
Real tempBot[2];
tempBot[0] = grid->get_u_value(leftU);
tempBot[1] = grid->get_v_value(gridV);
monoTriangulation2(tempTop, tempBot,
leftChain,
segIndexLarge+1,
leftEnd,
1, pStream);
}
if(segIndexLarge >= leftStart)
{
int do_optimize=1;
if(topVertex[0] >= grid->get_u_value(rightU))
do_optimize = 0;
else
{
int i;
for(i=leftStart; i<=segIndexSmall; i++)
if(leftChain->getVertex(i)[0] >= topVertex[0])
{
do_optimize = 0;
break;
}
}
if(do_optimize)
{
int midU=rightU;
while(grid->get_u_value(midU) >= topVertex[0])
{
midU--;
if(midU < leftU)
break;
}
midU++;
grid->outputFanWithPoint(gridV, midU, rightU, topVertex, pStream);
stripOfFanLeft(leftChain, segIndexLarge, segIndexSmall, grid, gridV, leftU, midU, pStream, 0);
Real tempBot[2];
tempBot[0] = grid->get_u_value(midU);
tempBot[1] = grid->get_v_value(gridV);
monoTriangulation2(topVertex, tempBot, leftChain, leftStart, segIndexSmall, 1, pStream);
}
else {
stripOfFanLeft(leftChain, segIndexLarge, segIndexSmall, grid, gridV, leftU, rightU, pStream, 0);
Real tempBot[2];
tempBot[0] = grid->get_u_value(rightU);
tempBot[1] = grid->get_v_value(gridV);
monoTriangulation2(topVertex, tempBot, leftChain, leftStart, segIndexSmall, 1, pStream);
}
}
else grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
}
void sampleTopLeftWithGridLine(Real* topVertex,
vertexArray* leftChain,
Int leftStart,
Int leftEnd,
gridWrap* grid,
Int gridV,
Int leftU,
Int rightU,
primStream* pStream
)
{
Int segIndexSmall, segIndexLarge;
if(leftEnd < leftStart) {
grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
return;
}
findTopLeftSegment(leftChain,
leftStart,
leftEnd,
grid->get_u_value(leftU),
segIndexSmall,
segIndexLarge
);
sampleTopLeftWithGridLinePost(topVertex,
leftChain,
leftStart,
segIndexSmall,
segIndexLarge,
leftEnd,
grid,
gridV,
leftU,
rightU,
pStream);
}
Int findTopSeparator(vertexArray* leftChain,
Int leftStartIndex,
Int leftEndIndex,
vertexArray* rightChain,
Int rightStartIndex,
Int rightEndIndex,
Int& ret_sep_left,
Int& ret_sep_right)
{
Int oldLeftI, oldRightI, newLeftI, newRightI;
Int i,j,k;
Real leftMax ;
Real rightMin ;
if(leftChain->getVertex(leftEndIndex)[1] > rightChain->getVertex(rightEndIndex)[1]) {
oldLeftI = leftEndIndex+1;
oldRightI = rightEndIndex;
leftMax = leftChain->getVertex(leftEndIndex)[0] - Real(1.0); rightMin = rightChain->getVertex(rightEndIndex)[0];
}
else
{
oldLeftI = leftEndIndex;
oldRightI = rightEndIndex+1;
leftMax = leftChain->getVertex(leftEndIndex)[0];
rightMin = rightChain->getVertex(rightEndIndex)[0] + Real(1.0);
}
i=leftEndIndex;
j=rightEndIndex;
while(1)
{
newLeftI = oldLeftI;
newRightI = oldRightI;
if(i<leftStartIndex) {
for(k=j-1; k>= rightStartIndex; k--)
{
if(rightChain->getVertex(k)[0] > leftMax) {
if(rightChain->getVertex(k)[0] < rightMin)
{
rightMin = rightChain->getVertex(k)[0];
oldRightI = k;
}
}
else break; }
break; }
else if(j<rightStartIndex) {
for(k=i-1; k>= leftStartIndex; k--)
{
if(leftChain->getVertex(k)[0] < rightMin) {
if(leftChain->getVertex(k)[0] > leftMax)
{
leftMax = leftChain->getVertex(k)[0];
oldLeftI = k;
}
}
else break; }
break; }
else if(leftChain->getVertex(i)[1] > rightChain->getVertex(j)[1]) {
if(leftChain->getVertex(i)[0] > leftMax) {
leftMax = leftChain->getVertex(i)[0];
newLeftI = i;
}
for(k=j-1; k>= rightStartIndex; k--) {
if(rightChain->getVertex(k)[1] > leftChain->getVertex(i)[1])
break;
if(rightChain->getVertex(k)[0] < rightMin)
{
rightMin = rightChain->getVertex(k)[0];
newRightI = k;
}
}
j = k; if(leftMax >= rightMin) break;
else {
oldLeftI = newLeftI;
oldRightI = newRightI;
}
}
else {
if(rightChain->getVertex(j)[0] < rightMin)
{
rightMin = rightChain->getVertex(j)[0];
newRightI = j;
}
for(k=i-1; k>= leftStartIndex; k--)
{
if(leftChain->getVertex(k)[1] > rightChain->getVertex(j)[1])
break;
if(leftChain->getVertex(k)[0] > leftMax)
{
leftMax = leftChain->getVertex(k)[0];
newLeftI = k;
}
}
i = k;
if(leftMax >= rightMin) break;
else {
oldLeftI = newLeftI;
oldRightI = newRightI;
}
}
} if(oldLeftI > leftEndIndex || oldRightI > rightEndIndex)
return 0;
else
{
ret_sep_left = oldLeftI;
ret_sep_right = oldRightI;
return 1;
}
}
void sampleCompTop(Real* topVertex,
vertexArray* leftChain,
Int leftStartIndex,
vertexArray* rightChain,
Int rightStartIndex,
gridBoundaryChain* leftGridChain,
gridBoundaryChain* rightGridChain,
Int gridIndex1,
Int up_leftCornerWhere,
Int up_leftCornerIndex,
Int up_rightCornerWhere,
Int up_rightCornerIndex,
primStream* pStream)
{
if(up_leftCornerWhere == 1 && up_rightCornerWhere == 1) {
leftGridChain->getGrid()->outputFanWithPoint(leftGridChain->getVlineIndex(gridIndex1),
leftGridChain->getUlineIndex(gridIndex1),
rightGridChain->getUlineIndex(gridIndex1),
topVertex,
pStream);
return;
}
else if(up_leftCornerWhere != 0)
{
Real* tempTop;
Int tempRightStart;
if(up_leftCornerWhere == 1){
tempRightStart = rightStartIndex;
tempTop = topVertex;
}
else
{
tempRightStart = up_leftCornerIndex+1;
tempTop = rightChain->getVertex(up_leftCornerIndex);
}
sampleTopRightWithGridLine(tempTop, rightChain, tempRightStart, up_rightCornerIndex,
rightGridChain->getGrid(),
leftGridChain->getVlineIndex(gridIndex1),
leftGridChain->getUlineIndex(gridIndex1),
rightGridChain->getUlineIndex(gridIndex1),
pStream);
}
else if(up_rightCornerWhere != 2)
{
Real* tempTop;
Int tempLeftStart;
if(up_rightCornerWhere == 1)
{
tempLeftStart = leftStartIndex;
tempTop = topVertex;
}
else {
tempLeftStart = up_rightCornerIndex+1;
tempTop = leftChain->getVertex(up_rightCornerIndex);
}
sampleCompTopSimple(topVertex,
leftChain,
leftStartIndex,
rightChain,
rightStartIndex,
leftGridChain,
rightGridChain,
gridIndex1,
up_leftCornerWhere,
up_leftCornerIndex,
up_rightCornerWhere,
up_rightCornerIndex,
pStream);
}
else {
sampleCompTopSimple(topVertex,
leftChain,
leftStartIndex,
rightChain,
rightStartIndex,
leftGridChain,
rightGridChain,
gridIndex1,
up_leftCornerWhere,
up_leftCornerIndex,
up_rightCornerWhere,
up_rightCornerIndex,
pStream);
return;
#ifdef NOT_REACHABLE //code is not reachable, for test purpose only
Int sep_left, sep_right;
if(findTopSeparator(leftChain,
leftStartIndex,
up_leftCornerIndex,
rightChain,
rightStartIndex,
up_rightCornerIndex,
sep_left,
sep_right)
) {
if( leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex1) &&
rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex1))
{
Int gridSep;
Int segLeftSmall, segLeftLarge, segRightSmall, segRightLarge;
Int valid=1; findTopLeftSegment(leftChain,
sep_left,
up_leftCornerIndex,
leftGridChain->get_u_value(gridIndex1),
segLeftSmall,
segLeftLarge);
findTopRightSegment(rightChain,
sep_right,
up_rightCornerIndex,
rightGridChain->get_u_value(gridIndex1),
segRightSmall,
segRightLarge);
if(leftChain->getVertex(segLeftSmall)[1] >= rightChain->getVertex(segRightSmall)[1])
{
gridSep = rightGridChain->getUlineIndex(gridIndex1);
while(leftGridChain->getGrid()->get_u_value(gridSep) > leftChain->getVertex(segLeftSmall)[0])
gridSep--;
if(segLeftSmall<segLeftLarge)
if(leftGridChain->getGrid()->get_u_value(gridSep) < leftChain->getVertex(segLeftSmall+1)[0])
{
valid = 0;
}
}
else
{
gridSep = leftGridChain->getUlineIndex(gridIndex1);
while(leftGridChain->getGrid()->get_u_value(gridSep) < rightChain->getVertex(segRightSmall)[0])
gridSep++;
if(segRightSmall<segRightLarge)
if(leftGridChain->getGrid()->get_u_value(gridSep) > rightChain->getVertex(segRightSmall+1)[0])
{
valid = 0;
}
}
if(! valid)
{
sampleCompTopSimple(topVertex,
leftChain,
leftStartIndex,
rightChain,
rightStartIndex,
leftGridChain,
rightGridChain,
gridIndex1,
up_leftCornerWhere,
up_leftCornerIndex,
up_rightCornerWhere,
up_rightCornerIndex,
pStream);
}
else
{
sampleTopLeftWithGridLinePost(leftChain->getVertex(segLeftSmall),
leftChain,
segLeftSmall+1,
segLeftSmall+1,
segLeftLarge,
up_leftCornerIndex,
leftGridChain->getGrid(),
leftGridChain->getVlineIndex(gridIndex1),
leftGridChain->getUlineIndex(gridIndex1),
gridSep,
pStream);
sampleTopRightWithGridLinePost(rightChain->getVertex(segRightSmall),
rightChain,
segRightSmall+1,
segRightSmall+1,
segRightLarge,
up_rightCornerIndex,
leftGridChain->getGrid(),
leftGridChain->getVlineIndex(gridIndex1),
gridSep,
rightGridChain->getUlineIndex(gridIndex1),
pStream);
Real tempBot[2];
tempBot[0] = leftGridChain->getGrid()->get_u_value(gridSep);
tempBot[1] = leftGridChain->get_v_value(gridIndex1);
monoTriangulationRecGen(topVertex, tempBot,
leftChain, leftStartIndex, segLeftSmall,
rightChain, rightStartIndex, segRightSmall,
pStream);
}
} else if(leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex1)) {
Int segLeftSmall, segLeftLarge;
findTopLeftSegment(leftChain,
sep_left,
up_leftCornerIndex,
leftGridChain->get_u_value(gridIndex1),
segLeftSmall,
segLeftLarge);
assert(segLeftLarge >= sep_left);
monoTriangulation2(leftChain->getVertex(segLeftLarge),
leftGridChain->get_vertex(gridIndex1),
leftChain,
segLeftLarge+1,
up_leftCornerIndex,
1, pStream);
stripOfFanLeft(leftChain, segLeftLarge, segLeftSmall,
leftGridChain->getGrid(),
leftGridChain->getVlineIndex(gridIndex1),
leftGridChain->getUlineIndex(gridIndex1),
rightGridChain->getUlineIndex(gridIndex1),
pStream, 0);
monoTriangulationRecGen(topVertex, rightGridChain->get_vertex(gridIndex1),
leftChain, leftStartIndex, segLeftSmall,
rightChain, rightStartIndex, up_rightCornerIndex,
pStream);
} else if(rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex1))
{
Int segRightSmall, segRightLarge;
findTopRightSegment(rightChain,
sep_right,
up_rightCornerIndex,
rightGridChain->get_u_value(gridIndex1),
segRightSmall,
segRightLarge);
assert(segRightLarge>=sep_right);
monoTriangulation2(rightChain->getVertex(segRightLarge),
rightGridChain->get_vertex(gridIndex1),
rightChain,
segRightLarge+1,
up_rightCornerIndex,
0, pStream);
stripOfFanRight(rightChain, segRightLarge, segRightSmall,
rightGridChain->getGrid(),
rightGridChain->getVlineIndex(gridIndex1),
leftGridChain->getUlineIndex(gridIndex1),
rightGridChain->getUlineIndex(gridIndex1),
pStream, 0);
monoTriangulationRecGen(topVertex, leftGridChain->get_vertex(gridIndex1),
leftChain, leftStartIndex, up_leftCornerIndex,
rightChain, rightStartIndex,segRightSmall,
pStream);
} else {
sampleCompTopSimple(topVertex,
leftChain,
leftStartIndex,
rightChain,
rightStartIndex,
leftGridChain,
rightGridChain,
gridIndex1,
up_leftCornerWhere,
up_leftCornerIndex,
up_rightCornerWhere,
up_rightCornerIndex,
pStream);
} } else {
sampleCompTopSimple(topVertex,
leftChain,
leftStartIndex,
rightChain,
rightStartIndex,
leftGridChain,
rightGridChain,
gridIndex1,
up_leftCornerWhere,
up_leftCornerIndex,
up_rightCornerWhere,
up_rightCornerIndex,
pStream);
}
#endif
}}
static void sampleCompTopSimpleOpt(gridWrap* grid,
Int gridV,
Real* topVertex, Real* botVertex,
vertexArray* inc_chain, Int inc_current, Int inc_end,
vertexArray* dec_chain, Int dec_current, Int dec_end,
primStream* pStream)
{
if(gridV <= 0 || dec_end<dec_current || inc_end <inc_current)
{
monoTriangulationRecGenOpt(topVertex, botVertex,
inc_chain, inc_current, inc_end,
dec_chain, dec_current, dec_end,
pStream);
return;
}
if(grid->get_v_value(gridV+1) >= topVertex[1])
{
monoTriangulationRecGenOpt(topVertex, botVertex,
inc_chain, inc_current, inc_end,
dec_chain, dec_current, dec_end,
pStream);
return;
}
Int i,j,k;
Real currentV = grid->get_v_value(gridV+1);
if(inc_chain->getVertex(inc_end)[1] <= currentV &&
dec_chain->getVertex(dec_end)[1] < currentV)
{
for(i=inc_end; i >= inc_current; i--)
{
if(inc_chain->getVertex(i)[1] > currentV)
break;
}
i++;
for(j=dec_end; j >= dec_current; j--)
{
if(dec_chain->getVertex(j)[1] >= currentV)
break;
}
j++;
if(inc_chain->getVertex(i)[1] <= dec_chain->getVertex(j)[1])
{
for(k=j; k<=dec_end; k++)
{
if(dec_chain->getVertex(k)[1] < inc_chain->getVertex(i)[1])
break;
}
int l;
Real tempI = Real(j);
Real tempMin = (Real)fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(j)[0]);
for(l=j+1; l<= k-1; l++)
{
if(fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(l)[0])
<= tempMin)
{
tempMin = (Real)fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(l)[0]);
tempI = (Real)l;
}
}
monoTriangulationRecGenOpt(dec_chain->getVertex((int)tempI),
botVertex,
inc_chain, i, inc_end,
dec_chain, (int)(tempI+1), dec_end,
pStream);
sampleCompTopSimpleOpt(grid,
gridV+1,
topVertex, inc_chain->getVertex(i),
inc_chain, inc_current, i-1,
dec_chain, dec_current, (int)tempI,
pStream);
}
else
{
for(k=i; k<=inc_end; k++)
{
if(inc_chain->getVertex(k)[1] <= dec_chain->getVertex(j)[1])
break;
}
int tempI = i;
int l;
Real tempMin = (Real)fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(j)[0]);
for(l=i+1; l<=k-1; l++)
{
if(fabs(inc_chain->getVertex(l)[0] - dec_chain->getVertex(j)[0]) <= tempMin)
{
tempMin = (Real)fabs(inc_chain->getVertex(l)[0] - dec_chain->getVertex(j)[0]);
tempI = l;
}
}
monoTriangulationRecGenOpt(inc_chain->getVertex(tempI),
botVertex,
inc_chain, tempI+1, inc_end,
dec_chain, j, dec_end,
pStream);
sampleCompTopSimpleOpt(grid, gridV+1,
topVertex, dec_chain->getVertex(j),
inc_chain, inc_current, tempI,
dec_chain, dec_current, j-1,
pStream);
}
}
else {
sampleCompTopSimpleOpt(grid,
gridV+1,
topVertex, botVertex,
inc_chain, inc_current, inc_end,
dec_chain, dec_current, dec_end,
pStream);
}
}
void sampleCompTopSimple(Real* topVertex,
vertexArray* leftChain,
Int leftStartIndex,
vertexArray* rightChain,
Int rightStartIndex,
gridBoundaryChain* leftGridChain,
gridBoundaryChain* rightGridChain,
Int gridIndex1,
Int up_leftCornerWhere,
Int up_leftCornerIndex,
Int up_rightCornerWhere,
Int up_rightCornerIndex,
primStream* pStream)
{
Int i,k;
Real* ActualTop;
Real* ActualBot;
Int ActualLeftStart, ActualLeftEnd;
Int ActualRightStart, ActualRightEnd;
gridWrap* grid = leftGridChain->getGrid();
Int gridV = leftGridChain->getVlineIndex(gridIndex1);
Int gridLeftU = leftGridChain->getUlineIndex(gridIndex1);
Int gridRightU = rightGridChain->getUlineIndex(gridIndex1);
Real2* gridPoints = (Real2*) malloc(sizeof(Real2) * (gridRightU - gridLeftU +1));
assert(gridPoints);
for(k=0, i=gridRightU; i>= gridLeftU; i--, k++)
{
gridPoints[k][0] = grid->get_u_value(i);
gridPoints[k][1] = grid->get_v_value(gridV);
}
if(up_leftCornerWhere != 2)
ActualRightStart = rightStartIndex;
else
ActualRightStart = up_leftCornerIndex+1;
if(up_rightCornerWhere != 2) ActualRightEnd = rightStartIndex-1; else
ActualRightEnd = up_rightCornerIndex;
vertexArray ActualRightChain(max(0, ActualRightEnd-ActualRightStart+1) + gridRightU-gridLeftU+1);
for(i=ActualRightStart; i<= ActualRightEnd; i++)
ActualRightChain.appendVertex(rightChain->getVertex(i));
for(i=0; i<gridRightU-gridLeftU+1; i++)
ActualRightChain.appendVertex(gridPoints[i]);
if(up_leftCornerWhere != 0)
ActualLeftEnd = leftStartIndex-1;
else
ActualLeftEnd = up_leftCornerIndex;
if(up_rightCornerWhere != 0)
ActualLeftStart = leftStartIndex;
else
ActualLeftStart = up_rightCornerIndex+1;
if(up_leftCornerWhere == 0)
{
if(up_rightCornerWhere == 0)
ActualTop = leftChain->getVertex(up_rightCornerIndex);
else
ActualTop = topVertex;
}
else if(up_leftCornerWhere == 1)
ActualTop = topVertex;
else ActualTop = rightChain->getVertex(up_leftCornerIndex);
ActualBot = gridPoints[gridRightU - gridLeftU];
if(leftChain->getVertex(ActualLeftEnd)[1] == ActualBot[1])
{
sampleCompTopSimpleOpt(grid, gridV,
ActualTop, leftChain->getVertex(ActualLeftEnd),
leftChain,
ActualLeftStart, ActualLeftEnd-1,
&ActualRightChain,
0,
ActualRightChain.getNumElements()-1,
pStream);
}
else
{
sampleCompTopSimpleOpt(grid, gridV,
ActualTop, ActualBot, leftChain,
ActualLeftStart, ActualLeftEnd,
&ActualRightChain,
0, ActualRightChain.getNumElements()-2, pStream);
}
free(gridPoints);
}