in UVAtlas/isochart/packingcharts.cpp [1713:1945]
inline static HRESULT MergeBorders(
PackingDirection direction,
VERTEX_ARRAY& atlasBorder,
VERTEX_ARRAY& chartBorder)
{
Axis TangentAxis = XAxis;
Axis RadialAxis = XAxis;
// If a vertex on one border is on the discardLocation
// side of another border, don't add it to the updated
// border
// For example, when updating left border, vertex A on
// border 1 is on the right side of border 2, A will be
// discarded
VertexLocation discardLocation = NotDefined;
bool bPackingFromLowerPlace = false;
switch (direction)
{
case FromRight:
{
discardLocation = LeftToBorder;
TangentAxis = YAxis; // y
RadialAxis = XAxis; // x
bPackingFromLowerPlace = false;
break;
}
case FromLeft:
{
discardLocation = RightToBorder;
TangentAxis = YAxis; // y
RadialAxis = XAxis; // x
bPackingFromLowerPlace = true;
break;
}
case FromTop:
{
discardLocation = BelowBorder;
TangentAxis = XAxis; // x
RadialAxis = YAxis; // y
bPackingFromLowerPlace = false;
break;
}
case FromBottom:
{
discardLocation = AboveBorder;
TangentAxis = XAxis; // x
RadialAxis = YAxis; // y
bPackingFromLowerPlace = true;
break;
}
default:
assert(false);
break;
}
size_t dwAtlasBorderSize = atlasBorder.size();
size_t dwChartBorderSize = chartBorder.size();
VertexLocation location;
float fDistance;
VERTEX_ARRAY tempBorder;
try
{
// 1. Before merge chart border and atlas border, find the
// correspond segments on each border. This operation is just
// used to decrease useless computation
size_t dwAtlasBorderStart, dwAtlasBorderEnd;
size_t dwChartBorderStart, dwChartBorderEnd;
if (!FindCorrespondSegmentsOfBorders(
atlasBorder,
chartBorder,
dwAtlasBorderStart,
dwAtlasBorderEnd,
dwChartBorderStart,
dwChartBorderEnd,
TangentAxis))
{
// if 2 borders have no correspond segments, just merge them according to
// the increasing order of coordinate in tangent direction
if (VECTOR_ITEM(&atlasBorder[dwAtlasBorderSize - 1]->uv, TangentAxis) <
VECTOR_ITEM(&chartBorder[0]->uv, TangentAxis))
{
atlasBorder.insert(atlasBorder.end(), chartBorder.cbegin(), chartBorder.cend());
}
else if (VECTOR_ITEM(&atlasBorder[0]->uv, TangentAxis) >
VECTOR_ITEM(&chartBorder[dwChartBorderSize - 1]->uv, TangentAxis))
{
tempBorder.insert(tempBorder.end(), atlasBorder.cbegin(), atlasBorder.cend());
atlasBorder.clear();
atlasBorder.insert(atlasBorder.end(), chartBorder.cbegin(), chartBorder.cend());
atlasBorder.insert(atlasBorder.end(), tempBorder.cbegin(), tempBorder.cend());
}
else
{
assert(false);
}
return S_OK;
}
// 2. Add vertices before correspond segments into new border
for (size_t i = 0; i < dwAtlasBorderStart; i++)
{
tempBorder.push_back(atlasBorder[i]);
}
for (size_t i = 0; i < dwChartBorderStart; i++)
{
tempBorder.push_back(chartBorder[i]);
}
// 3. Merge the correspond segments
size_t ii = dwAtlasBorderStart;
size_t jj = dwChartBorderStart;
while (ii <= dwAtlasBorderEnd && jj <= dwChartBorderEnd)
{
float tangent1 = VECTOR_ITEM(&atlasBorder[ii]->uv, TangentAxis);
float tangent2 = VECTOR_ITEM(&chartBorder[jj]->uv, TangentAxis);
// 3.1 Check if current vertex on old atlas border can be a vertex
// on new atlas border
if (tangent1 < tangent2)
{
location = CalculateVertexLocationToBorder(
chartBorder,
dwChartBorderStart,
dwChartBorderEnd,
atlasBorder[ii]->uv,
0,
fDistance,
TangentAxis);
if (location != discardLocation)
{
tempBorder.push_back(atlasBorder[ii]);
}
dwAtlasBorderStart = ii;
ii++;
}
// 3.2 Check if current vertex on chart border can be a vertex
// on new atlas border
else if (tangent1 > tangent2)
{
location = CalculateVertexLocationToBorder(
atlasBorder,
dwAtlasBorderStart,
dwAtlasBorderEnd,
chartBorder[jj]->uv,
0,
fDistance,
TangentAxis);
if (location != discardLocation)
{
tempBorder.push_back(chartBorder[jj]);
}
dwChartBorderStart = jj;
jj++;
}
// 3.3 compare 2 vertices on different borders, and add
// one into new atlas border.
else
{
float fRadia1 = VECTOR_ITEM(&atlasBorder[ii]->uv, RadialAxis);
float fRadia2 = VECTOR_ITEM(&chartBorder[jj]->uv, RadialAxis);
if (bPackingFromLowerPlace)
{
if (fRadia1 < fRadia2)
{
tempBorder.push_back(atlasBorder[ii]);
}
else if (fRadia1 > fRadia2)
{
tempBorder.push_back(chartBorder[jj]);
}
else
{
tempBorder.push_back(chartBorder[jj]);
//assert(fRadia1 != fRadia2);
}
}
else
{
if (fRadia1 > fRadia2)
{
tempBorder.push_back(atlasBorder[ii]);
}
else if (fRadia1 < fRadia2)
{
tempBorder.push_back(chartBorder[jj]);
}
else
{
tempBorder.push_back(chartBorder[jj]);
//assert(fRadia1 != fRadia2);
}
}
dwAtlasBorderStart = ii;
dwChartBorderStart = jj;
ii++;
jj++;
}
}
// 4. Add vertices after correspond segments into new border
for (size_t i = ii; i < dwAtlasBorderSize; i++)
{
tempBorder.push_back(atlasBorder[i]);
}
for (size_t i = jj; i < dwChartBorderSize; i++)
{
tempBorder.push_back(chartBorder[i]);
}
// 6. Update atlas border.
atlasBorder.clear();
atlasBorder.insert(atlasBorder.end(), tempBorder.cbegin(), tempBorder.cend());
}
catch (std::bad_alloc&)
{
return E_OUTOFMEMORY;
}
return S_OK;
}