You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
231 lines
6.5 KiB
C++
231 lines
6.5 KiB
C++
|
2 weeks ago
|
/*=========================================================================
|
||
|
|
|
||
|
|
Program: Visualization Toolkit
|
||
|
|
Module: vtkBezierContourLineInterpolator.cxx
|
||
|
|
|
||
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
||
|
|
All rights reserved.
|
||
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
||
|
|
|
||
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
||
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||
|
|
PURPOSE. See the above copyright notice for more information.
|
||
|
|
|
||
|
|
=========================================================================*/
|
||
|
|
#include "vtkBezierContourLineInterpolator.h"
|
||
|
|
|
||
|
|
#include "vtkContourRepresentation.h"
|
||
|
|
#include "vtkMath.h"
|
||
|
|
#include "vtkObjectFactory.h"
|
||
|
|
#include "vtkRenderer.h"
|
||
|
|
#include "vtkIntArray.h"
|
||
|
|
|
||
|
|
vtkStandardNewMacro(vtkBezierContourLineInterpolator);
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------
|
||
|
|
vtkBezierContourLineInterpolator::vtkBezierContourLineInterpolator()
|
||
|
|
{
|
||
|
|
this->MaximumCurveError = 0.005;
|
||
|
|
this->MaximumCurveLineSegments = 100;
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------
|
||
|
|
vtkBezierContourLineInterpolator::~vtkBezierContourLineInterpolator()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------
|
||
|
|
int vtkBezierContourLineInterpolator::InterpolateLine( vtkRenderer *vtkNotUsed(ren),
|
||
|
|
vtkContourRepresentation *rep,
|
||
|
|
int idx1, int idx2 )
|
||
|
|
{
|
||
|
|
int maxRecursion = 0;
|
||
|
|
int tmp = 3;
|
||
|
|
|
||
|
|
while ( 2*tmp < this->MaximumCurveLineSegments )
|
||
|
|
{
|
||
|
|
tmp *= 2;
|
||
|
|
maxRecursion++;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( maxRecursion == 0 )
|
||
|
|
{
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
// There are four control points with 3 components each, plus one
|
||
|
|
// value for the recursion depth of this point
|
||
|
|
double *controlPointsStack = new double[(3*4+1)*(maxRecursion+1)];
|
||
|
|
int stackCount = 0;
|
||
|
|
|
||
|
|
double slope1[3];
|
||
|
|
double slope2[3];
|
||
|
|
|
||
|
|
rep->GetNthNodeSlope( idx1, slope1 );
|
||
|
|
rep->GetNthNodeSlope( idx2, slope2 );
|
||
|
|
|
||
|
|
controlPointsStack[0] = 0;
|
||
|
|
double *p1 = controlPointsStack+1;
|
||
|
|
double *p2 = controlPointsStack+4;
|
||
|
|
double *p3 = controlPointsStack+7;
|
||
|
|
double *p4 = controlPointsStack+10;
|
||
|
|
|
||
|
|
rep->GetNthNodeWorldPosition( idx1, p1 );
|
||
|
|
rep->GetNthNodeWorldPosition( idx2, p4 );
|
||
|
|
|
||
|
|
double distance = sqrt( vtkMath::Distance2BetweenPoints( p1, p4 ) );
|
||
|
|
|
||
|
|
p2[0] = p1[0] + .333*distance*slope1[0];
|
||
|
|
p2[1] = p1[1] + .333*distance*slope1[1];
|
||
|
|
p2[2] = p1[2] + .333*distance*slope1[2];
|
||
|
|
|
||
|
|
p3[0] = p4[0] - .333*distance*slope2[0];
|
||
|
|
p3[1] = p4[1] - .333*distance*slope2[1];
|
||
|
|
p3[2] = p4[2] - .333*distance*slope2[2];
|
||
|
|
|
||
|
|
stackCount++;
|
||
|
|
|
||
|
|
while ( stackCount )
|
||
|
|
{
|
||
|
|
//process last point on stack
|
||
|
|
int recursionLevel = static_cast<int>(controlPointsStack[13*(stackCount-1)]);
|
||
|
|
|
||
|
|
p1 = controlPointsStack + 13*(stackCount-1)+1;
|
||
|
|
p2 = controlPointsStack + 13*(stackCount-1)+4;
|
||
|
|
p3 = controlPointsStack + 13*(stackCount-1)+7;
|
||
|
|
p4 = controlPointsStack + 13*(stackCount-1)+10;
|
||
|
|
|
||
|
|
double totalDist = 0;
|
||
|
|
totalDist += sqrt(vtkMath::Distance2BetweenPoints(p1,p2));
|
||
|
|
totalDist += sqrt(vtkMath::Distance2BetweenPoints(p2,p3));
|
||
|
|
totalDist += sqrt(vtkMath::Distance2BetweenPoints(p3,p4));
|
||
|
|
|
||
|
|
distance = sqrt(vtkMath::Distance2BetweenPoints(p1,p4));
|
||
|
|
|
||
|
|
if ( recursionLevel >= maxRecursion || distance == 0 ||
|
||
|
|
(totalDist - distance)/distance < this->MaximumCurveError )
|
||
|
|
{
|
||
|
|
rep->AddIntermediatePointWorldPosition( idx1, p2 );
|
||
|
|
rep->AddIntermediatePointWorldPosition( idx1, p3 );
|
||
|
|
|
||
|
|
if ( stackCount > 1 )
|
||
|
|
{
|
||
|
|
rep->AddIntermediatePointWorldPosition( idx1, p4 );
|
||
|
|
}
|
||
|
|
stackCount--;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
double p12[3], p23[3], p34[3], p123[3], p234[3], p1234[3];
|
||
|
|
|
||
|
|
this->ComputeMidpoint( p1, p2, p12 );
|
||
|
|
this->ComputeMidpoint( p2, p3, p23 );
|
||
|
|
this->ComputeMidpoint( p3, p4, p34 );
|
||
|
|
this->ComputeMidpoint( p12, p23, p123 );
|
||
|
|
this->ComputeMidpoint( p23, p34, p234 );
|
||
|
|
this->ComputeMidpoint( p123, p234, p1234 );
|
||
|
|
|
||
|
|
// add these two points to the stack
|
||
|
|
controlPointsStack[13*(stackCount-1)] = recursionLevel+1;
|
||
|
|
controlPointsStack[13*(stackCount)] = recursionLevel+1;
|
||
|
|
|
||
|
|
double *newp1 = controlPointsStack + 13*(stackCount)+1;
|
||
|
|
double *newp2 = controlPointsStack + 13*(stackCount)+4;
|
||
|
|
double *newp3 = controlPointsStack + 13*(stackCount)+7;
|
||
|
|
double *newp4 = controlPointsStack + 13*(stackCount)+10;
|
||
|
|
|
||
|
|
newp1[0] = p1[0];
|
||
|
|
newp1[1] = p1[1];
|
||
|
|
newp1[2] = p1[2];
|
||
|
|
|
||
|
|
newp2[0] = p12[0];
|
||
|
|
newp2[1] = p12[1];
|
||
|
|
newp2[2] = p12[2];
|
||
|
|
|
||
|
|
newp3[0] = p123[0];
|
||
|
|
newp3[1] = p123[1];
|
||
|
|
newp3[2] = p123[2];
|
||
|
|
|
||
|
|
newp4[0] = p1234[0];
|
||
|
|
newp4[1] = p1234[1];
|
||
|
|
newp4[2] = p1234[2];
|
||
|
|
|
||
|
|
p1[0] = p1234[0];
|
||
|
|
p1[1] = p1234[1];
|
||
|
|
p1[2] = p1234[2];
|
||
|
|
|
||
|
|
p2[0] = p234[0];
|
||
|
|
p2[1] = p234[1];
|
||
|
|
p2[2] = p234[2];
|
||
|
|
|
||
|
|
p3[0] = p34[0];
|
||
|
|
p3[1] = p34[1];
|
||
|
|
p3[2] = p34[2];
|
||
|
|
|
||
|
|
stackCount++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
delete [] controlPointsStack;
|
||
|
|
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------
|
||
|
|
void vtkBezierContourLineInterpolator::GetSpan( int nodeIndex,
|
||
|
|
vtkIntArray *nodeIndices,
|
||
|
|
vtkContourRepresentation *rep)
|
||
|
|
{
|
||
|
|
int start = nodeIndex - 2;
|
||
|
|
int end = nodeIndex - 1;
|
||
|
|
int index[2];
|
||
|
|
|
||
|
|
// Clear the array
|
||
|
|
nodeIndices->Reset();
|
||
|
|
nodeIndices->Squeeze();
|
||
|
|
nodeIndices->SetNumberOfComponents(2);
|
||
|
|
|
||
|
|
for ( int i = 0; i < 4; i++ )
|
||
|
|
{
|
||
|
|
index[0] = start++;
|
||
|
|
index[1] = end++;
|
||
|
|
|
||
|
|
if ( rep->GetClosedLoop() )
|
||
|
|
{
|
||
|
|
if ( index[0] < 0 )
|
||
|
|
{
|
||
|
|
index[0] += rep->GetNumberOfNodes();
|
||
|
|
}
|
||
|
|
if ( index[1] < 0 )
|
||
|
|
{
|
||
|
|
index[1] += rep->GetNumberOfNodes();
|
||
|
|
}
|
||
|
|
if ( index[0] >= rep->GetNumberOfNodes() )
|
||
|
|
{
|
||
|
|
index[0] -= rep->GetNumberOfNodes();
|
||
|
|
}
|
||
|
|
if ( index[1] >= rep->GetNumberOfNodes() )
|
||
|
|
{
|
||
|
|
index[1] -= rep->GetNumberOfNodes();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( index[0] >= 0 && index[0] < rep->GetNumberOfNodes() &&
|
||
|
|
index[1] >= 0 && index[1] < rep->GetNumberOfNodes() )
|
||
|
|
{
|
||
|
|
nodeIndices->InsertNextTypedTuple( index );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------
|
||
|
|
void vtkBezierContourLineInterpolator::PrintSelf(ostream& os, vtkIndent indent)
|
||
|
|
{
|
||
|
|
this->Superclass::PrintSelf(os,indent);
|
||
|
|
|
||
|
|
os << indent << "Maximum Curve Error: " << this->MaximumCurveError << "\n";
|
||
|
|
os << indent << "Maximum Curve Line Segments: "
|
||
|
|
<< this->MaximumCurveLineSegments << "\n";
|
||
|
|
}
|
||
|
|
|