in UVAtlas/isochart/isochartmesh.cpp [1184:1363]
HRESULT CIsochartMesh::IsomapParameterlization(
bool& bIsLikePlane,
size_t& dwPrimaryEigenDimension,
size_t& dwMaxEigenDimension,
float** ppfVertGeodesicDistance,
float** ppfVertCombineDistance,
float** ppfVertMappingCoord)
{
assert(ppfVertGeodesicDistance != nullptr);
assert(ppfVertCombineDistance != nullptr);
assert(ppfVertMappingCoord != nullptr);
HRESULT hr = S_OK;
bIsLikePlane = false;
bool bIsSignalSpecialized = IsIMTSpecified();
float* pfVertGeodesicDistance = nullptr;
float* pfVertCombinedDistance = nullptr;
float* pfGeodesicMatrix = nullptr;
float* pfVertMappingCoord = nullptr;
size_t dwLandmarkNumber = 0;
size_t dwCalculatedDimension = 0;
// 1. Calculate the landmark vertices
if (FAILED(hr = CalculateLandmarkVertices(
MIN_LANDMARK_NUMBER,
dwLandmarkNumber)))
{
goto LEnd;
}
// 2. Calculate the geodesic distance matrix of landmark vertices
pfVertGeodesicDistance = new (std::nothrow) float[dwLandmarkNumber * m_dwVertNumber];
if (bIsSignalSpecialized)
{
pfVertCombinedDistance = new (std::nothrow) float[dwLandmarkNumber * m_dwVertNumber];
}
else
{
pfVertCombinedDistance = pfVertGeodesicDistance;
}
pfGeodesicMatrix = new (std::nothrow) float[dwLandmarkNumber * dwLandmarkNumber];
if (!pfVertGeodesicDistance || !pfGeodesicMatrix || !pfVertCombinedDistance)
{
hr = E_OUTOFMEMORY;
goto LEnd;
}
if (FAILED(hr = CalculateGeodesicDistance(
m_landmarkVerts,
pfVertCombinedDistance,
pfVertGeodesicDistance)))
{
goto LEnd;
}
#if USING_COMBINED_DISTANCE_TO_PARAMETERIZE
CalculateGeodesicMatrix(
m_landmarkVerts,
pfVertCombinedDistance,
pfGeodesicMatrix);
#else
CalculateGeodesicMatrix(
m_landmarkVerts,
pfVertGeodesicDistance,
pfGeodesicMatrix);
#endif
// 4. Perform Isomap to do surface spectral analysis
if (m_bIsSubChart)
{
dwMaxEigenDimension = std::min(SUB_CHART_EIGEN_DIMENSION, dwLandmarkNumber);
}
else
{
dwMaxEigenDimension = std::min(ORIGINAL_CHART_EIGEN_DIMENSION, dwLandmarkNumber);
}
if (FAILED(hr = m_isoMap.Init(
dwLandmarkNumber,
pfGeodesicMatrix)))
{
goto LEnd;
}
if (FAILED(hr = m_isoMap.ComputeLargestEigen(
dwMaxEigenDimension,
dwCalculatedDimension)))
{
goto LEnd;
}
SAFE_DELETE_ARRAY(pfGeodesicMatrix)
assert(dwMaxEigenDimension >= dwCalculatedDimension);
dwMaxEigenDimension = dwCalculatedDimension;
dwPrimaryEigenDimension = 0;
if (FAILED(hr = m_isoMap.GetPrimaryEnergyDimension(
PRIMARY_EIGEN_ENERGY_PERCENT,
dwPrimaryEigenDimension)))
{
goto LEnd;
}
// If current chart degenerated to a point, dwPrimaryEigenDimension
// will equal to 0
if (0 == dwPrimaryEigenDimension)
{
goto LEnd;
}
if (FAILED(hr = ProcessPlaneLikeShape(
dwCalculatedDimension,
dwPrimaryEigenDimension,
bIsLikePlane)) || bIsLikePlane)
{
goto LEnd;
}
// if CIsomap::GetPrimaryEnergyDimension discard too many vector
// demensions which are needed by special-shape detecting, just
// set it back to DIMENSION_TO_CHECK_SPECIAL_SHAPE
if (dwPrimaryEigenDimension < DIMENSION_TO_CHECK_SPECIAL_SHAPE
&& dwCalculatedDimension >= DIMENSION_TO_CHECK_SPECIAL_SHAPE)
{
dwPrimaryEigenDimension = DIMENSION_TO_CHECK_SPECIAL_SHAPE;
}
//5. Compute n-dimensional embedding coordinates of each vertex
// here, n = dwPrimaryEigenDimension
pfVertMappingCoord = new (std::nothrow) float[m_dwVertNumber * dwPrimaryEigenDimension];
if (!pfVertMappingCoord)
{
hr = E_OUTOFMEMORY;
goto LEnd;
}
#if USING_COMBINED_DISTANCE_TO_PARAMETERIZE
if (FAILED(hr = CalculateVertMappingCoord(
pfVertCombinedDistance,
dwLandmarkNumber,
dwPrimaryEigenDimension,
pfVertMappingCoord)))
{
goto LEnd;
}
#else
if (FAILED(hr = CalculateVertMappingCoord(
pfVertGeodesicDistance,
dwLandmarkNumber,
dwPrimaryEigenDimension,
pfVertMappingCoord)))
{
goto LEnd;
}
#endif
m_bIsParameterized = true;
LEnd:
SAFE_DELETE_ARRAY(pfGeodesicMatrix)
if (FAILED(hr))
{
SAFE_DELETE_ARRAY(pfVertGeodesicDistance)
if (bIsSignalSpecialized)
{
SAFE_DELETE_ARRAY(pfVertCombinedDistance)
}
SAFE_DELETE_ARRAY(pfVertMappingCoord)
}
else
{
*ppfVertCombineDistance = pfVertCombinedDistance;
*ppfVertGeodesicDistance = pfVertGeodesicDistance;
*ppfVertMappingCoord = pfVertMappingCoord;
}
return hr;
}