|
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
|
#include "Skeleton.h"
|
|
|
|
|
|
#include "PublicFunctions.h"
|
|
|
|
|
|
|
|
|
|
|
|
CPublicFunctions g_bf;
|
|
|
|
|
|
CPublicFunctions* AfxGetBaseFunction()
|
|
|
|
|
|
{
|
|
|
|
|
|
return &g_bf;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GPlineSkeleton::GPlineSkeleton()
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GPlineSkeleton::~GPlineSkeleton()
|
|
|
|
|
|
{
|
|
|
|
|
|
Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GPlineSkeleton::Clear(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_skeletonLines.clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double GPlineSkeleton::GetCurveAngle(GPline& curve, double l, double step)
|
|
|
|
|
|
{
|
|
|
|
|
|
//int i=of.BinarySearch(l,curve.num,curve.l);
|
|
|
|
|
|
//if(i>0 && i<curve.num-1)
|
|
|
|
|
|
// return _GetAngle(curve.x[i-1],curve.y[i-1],curve.x[i],curve.y[i],curve.x[i+1],curve.y[i+1]);
|
|
|
|
|
|
//return 0;
|
|
|
|
|
|
GPoint3D p1,p2,p3;
|
|
|
|
|
|
curve.GetCoordinate(l-step,p1.x0,p1.y0,p1.z0);
|
|
|
|
|
|
curve.GetCoordinate(l,p2.x0,p2.y0,p2.z0);
|
|
|
|
|
|
curve.GetCoordinate(l+step,p3.x0,p3.y0,p3.z0);
|
|
|
|
|
|
return AfxGetBaseFunction()->GetAngle(p1.x0,p1.y0,p2.x0,p2.y0,p3.x0,p3.y0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int GPlineSkeleton::GetMinAngle(GPline &curve,double step)
|
|
|
|
|
|
{
|
|
|
|
|
|
int i,j;
|
|
|
|
|
|
double t,s;
|
|
|
|
|
|
j=0;
|
|
|
|
|
|
s=0;
|
|
|
|
|
|
for(i=1;i<curve.GetCount()-1,++i)
|
|
|
|
|
|
{
|
|
|
|
|
|
t=GetCurveAngle(curve,curve.L(i)+1e-10,step*0.1);
|
|
|
|
|
|
t=fabs(t);
|
|
|
|
|
|
if(t>s)
|
|
|
|
|
|
{
|
|
|
|
|
|
s=t;
|
|
|
|
|
|
j=i;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return j;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int GPlineSkeleton::Create(GPline &curve,double step)
|
|
|
|
|
|
{
|
|
|
|
|
|
list.clear();
|
|
|
|
|
|
|
|
|
|
|
|
int i,j,k;
|
|
|
|
|
|
j=GetMinAngle(curve,step);
|
|
|
|
|
|
|
|
|
|
|
|
double l0,lmax;
|
|
|
|
|
|
GPoint3D point;
|
|
|
|
|
|
|
|
|
|
|
|
i=j;
|
|
|
|
|
|
point.x0=curve.X(i);
|
|
|
|
|
|
point.y0=curve.Y(i);
|
|
|
|
|
|
list.push_back(point);
|
|
|
|
|
|
lmax=curve.L(curve.GetCount()-1);
|
|
|
|
|
|
l0 =curve.L(j)+step;
|
|
|
|
|
|
while(l0<lmax)
|
|
|
|
|
|
{
|
|
|
|
|
|
i++;
|
|
|
|
|
|
while(l0<curve.L(i) )
|
|
|
|
|
|
{
|
|
|
|
|
|
k=AfxGetBaseFunction()->BinarySearch(l0,curve.num,curve.l);
|
|
|
|
|
|
point.x0=AfxGetBaseFunction()->LineValue(l0,curve.l+k,curve.x+k);
|
|
|
|
|
|
point.y0=AfxGetBaseFunction()->LineValue(l0,curve.l+k,curve.y+k);
|
|
|
|
|
|
list.push_back(point);
|
|
|
|
|
|
l0+=step;
|
|
|
|
|
|
}
|
|
|
|
|
|
point.x0=curve.x[i];
|
|
|
|
|
|
point.y0=curve.y[i];
|
|
|
|
|
|
list.push_back(point);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
i=0;
|
|
|
|
|
|
point.x0=curve.X(i);
|
|
|
|
|
|
point.y0=curve.Y(i);
|
|
|
|
|
|
list.push_back(point);
|
|
|
|
|
|
lmax=curve.l[j];
|
|
|
|
|
|
l0=curve.l[0]+step;
|
|
|
|
|
|
while(l0<lmax)
|
|
|
|
|
|
{
|
|
|
|
|
|
i++;
|
|
|
|
|
|
while(l0<curve.l[i])
|
|
|
|
|
|
{
|
|
|
|
|
|
k=AfxGetBaseFunction()->BinarySearch(l0,curve.num,curve.l);
|
|
|
|
|
|
point.x0=AfxGetBaseFunction()->LineValue(l0,curve.l+k,curve.x+k);
|
|
|
|
|
|
point.y0=AfxGetBaseFunction()->LineValue(l0,curve.l+k,curve.y+k);
|
|
|
|
|
|
list.push_back(point);
|
|
|
|
|
|
l0+=step;
|
|
|
|
|
|
}
|
|
|
|
|
|
point.x0=curve.x[i];
|
|
|
|
|
|
point.y0=curve.y[i];
|
|
|
|
|
|
list.push_back(point);
|
|
|
|
|
|
}
|
|
|
|
|
|
point.x0=curve.x[j];
|
|
|
|
|
|
point.y0=curve.y[j];
|
|
|
|
|
|
list.push_back(point);
|
|
|
|
|
|
list.AddHead(point);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GPlineSkeleton::GetFirstTriangle(CSkeletonTriangle &tri)
|
|
|
|
|
|
{
|
|
|
|
|
|
tri.p1=list.GetHeadPosition();
|
|
|
|
|
|
|
|
|
|
|
|
tri.p2=tri.p1;
|
|
|
|
|
|
list.GetNext(tri.p2);
|
|
|
|
|
|
tri.p3=list.GetTailPosition();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int GPlineSkeleton::GetNext(CSkeletonTriangle &tri)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(tri.p2==tri.p3 || tri.p1==NULL || tri.p2==NULL || tri.p3==NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
CSklTriPoint pp;
|
|
|
|
|
|
pp.p1=list.GetAt(tri.p1);
|
|
|
|
|
|
pp.p2=list.GetAt(tri.p2);
|
|
|
|
|
|
pp.p3=list.GetAt(tri.p3);
|
|
|
|
|
|
|
|
|
|
|
|
SKLINE* fw = &m_skeletonLines.back();
|
|
|
|
|
|
|
|
|
|
|
|
pp.Write23(fw);
|
|
|
|
|
|
|
|
|
|
|
|
POSITION p,pm,prev,next,pold;
|
|
|
|
|
|
pm=NULL;
|
|
|
|
|
|
double t,s;
|
|
|
|
|
|
s=1e300;
|
|
|
|
|
|
pold=tri.p1;
|
|
|
|
|
|
p=tri.p2; list.GetNext(p); next=p;
|
|
|
|
|
|
prev=tri.p3; list.GetPrev(prev);
|
|
|
|
|
|
if(p==NULL)return 0;
|
|
|
|
|
|
while(p!=tri.p3)
|
|
|
|
|
|
{
|
|
|
|
|
|
pp.p1=list.GetAt(p);
|
|
|
|
|
|
t=pp.Value();
|
|
|
|
|
|
if(t<s)
|
|
|
|
|
|
{
|
|
|
|
|
|
s=t;
|
|
|
|
|
|
pm=p;
|
|
|
|
|
|
}
|
|
|
|
|
|
list.GetNext(p);
|
|
|
|
|
|
if(p==NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
::AfxMessageBox("Bad process");
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if(pm==next)
|
|
|
|
|
|
{
|
|
|
|
|
|
tri.p1=tri.p2;
|
|
|
|
|
|
tri.p2=pm;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if(pm==prev)
|
|
|
|
|
|
{
|
|
|
|
|
|
tri.p1=tri.p3;
|
|
|
|
|
|
tri.p3=pm;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
pp.Write23(fw);
|
|
|
|
|
|
|
|
|
|
|
|
CSkeletonTriangle tri2,tri1;
|
|
|
|
|
|
tri1=tri;
|
|
|
|
|
|
tri2=tri;
|
|
|
|
|
|
tri1.p1=tri1.p2;
|
|
|
|
|
|
tri1.p2=pm;
|
|
|
|
|
|
tri2.p1=tri2.p3;
|
|
|
|
|
|
tri2.p3=pm;
|
|
|
|
|
|
Trace(tri1);
|
|
|
|
|
|
Trace(tri2);
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double GPlineSkeleton::CSklTriPoint::Value()
|
|
|
|
|
|
{
|
|
|
|
|
|
return AfxGetBaseFunction()->Distance(p1.x0,p1.y0,p2.x0,p2.y0) +
|
|
|
|
|
|
AfxGetBaseFunction()->Distance(p1.x0,p1.y0,p3.x0,p3.y0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GPlineSkeleton::CSklTriPoint::Write12(SKLINE *&fw)
|
|
|
|
|
|
{
|
|
|
|
|
|
////fprintf(fw,"%lf,%lf,%lf\n",(p1.x0+p2.x0)*0.5,(p1.y0+p2.y0)*0.5,_Distance(p2.x0,p2.y0,p1.x0,p1.y0));
|
|
|
|
|
|
//fprintf(fw,"%lf,%lf\n",(p1.x0+p2.x0)*0.5,(p1.y0+p2.y0)*0.5);
|
|
|
|
|
|
|
|
|
|
|
|
fw->push_back(GPoint3D((p1.x0+p2.x0)*0.5,(p1.y0+p2.y0)*0.5));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GPlineSkeleton::CSklTriPoint::Write23(SKLINE *&fw)
|
|
|
|
|
|
{
|
|
|
|
|
|
////fprintf(fw,"%lf,%lf,%lf\n",(p2.x0+p3.x0)*0.5,(p2.y0+p3.y0)*0.5,_Distance(p2.x0,p2.y0,p3.x0,p3.y0));
|
|
|
|
|
|
//fprintf(fw,"%lf,%lf\n",(p2.x0+p3.x0)*0.5,(p2.y0+p3.y0)*0.5);
|
|
|
|
|
|
fw->push_back(GPoint3D((p2.x0+p3.x0)*0.5,(p2.y0+p3.y0)*0.5)) ;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GPlineSkeleton::Trace(CSkeletonTriangle &tri)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(tri.p1==NULL || tri.p2==NULL || tri.p3==NULL) return;
|
|
|
|
|
|
#ifndef _GDF_QT
|
|
|
|
|
|
if(!AfxIsValidAddress(tri.p1, sizeof(tri.p1))) return;
|
|
|
|
|
|
if(!AfxIsValidAddress(tri.p2, sizeof(tri.p2))) return;
|
|
|
|
|
|
if(!AfxIsValidAddress(tri.p3, sizeof(tri.p3))) return;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//if(name.IsEmpty()) fprintf(fw,"Pline\n");
|
|
|
|
|
|
//else fprintf(fw,"Pline.%s\n",name);
|
|
|
|
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>SKLINE
|
|
|
|
|
|
m_skeletonLines.push_back(SKLINE());
|
|
|
|
|
|
|
|
|
|
|
|
CSklTriPoint pp;
|
|
|
|
|
|
pp.p1=list.GetAt(tri.p1);
|
|
|
|
|
|
pp.p2=list.GetAt(tri.p2);
|
|
|
|
|
|
pp.p3=list.GetAt(tri.p3);
|
|
|
|
|
|
SKLINE* fw = &m_skeletonLines.back();
|
|
|
|
|
|
pp.Write12(fw);
|
|
|
|
|
|
while(GetNext(tri));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GPlineSkeleton::Trace(GPline* curve, double step)
|
|
|
|
|
|
{
|
|
|
|
|
|
GPline* pc = RemoveRepeatPoint(curve);
|
|
|
|
|
|
Create(*pc,step);
|
|
|
|
|
|
delete pc;
|
|
|
|
|
|
//Create(curve,step);
|
|
|
|
|
|
|
|
|
|
|
|
CSkeletonTriangle tri;
|
|
|
|
|
|
GetFirstTriangle(tri);
|
|
|
|
|
|
Trace(tri);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GPline* GPlineSkeleton::RemoveRepeatPoint(GPline* pc)
|
|
|
|
|
|
{
|
|
|
|
|
|
GPline* c = new GPline();// (pc->GetCount());
|
|
|
|
|
|
if(!pc->GetName().empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
string str=pc->GetName();
|
|
|
|
|
|
c->SetName(str);
|
|
|
|
|
|
}
|
|
|
|
|
|
int sel=0;
|
|
|
|
|
|
int j=0;
|
|
|
|
|
|
|
|
|
|
|
|
//c->SetPoint(0, pc->GetPoint(0));
|
|
|
|
|
|
c->AddPoint(pc->GetPoint(0));
|
|
|
|
|
|
j++;
|
|
|
|
|
|
BOOL bEnd=FALSE;
|
|
|
|
|
|
for(int i=1;i<pc->GetCount();i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
sel=i-1;
|
|
|
|
|
|
while(AfxGetBaseFunction()->Distance(pc->X(i),pc->Y(i),pc->X(sel),pc->Y(sel))<1e-6)
|
|
|
|
|
|
{
|
|
|
|
|
|
i++;
|
|
|
|
|
|
if(i>pc->GetCount()-1) { bEnd=TRUE; break; }
|
|
|
|
|
|
}
|
|
|
|
|
|
if(bEnd)
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
//c->SetPoint(j, pc->GetPoint(i));
|
|
|
|
|
|
c->AddPoint(pc->GetPoint(i));
|
|
|
|
|
|
j++;
|
|
|
|
|
|
}
|
|
|
|
|
|
//c->nPoint=2;
|
|
|
|
|
|
//c->num=j;
|
|
|
|
|
|
//c->GetLocation();
|
|
|
|
|
|
return c;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GPline* GPlineSkeleton::CreateSkeletonCurve(int nIndex) //<2F><><EFBFBD>ݹ<EFBFBD><DDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>GPline<6E><65><EFBFBD><EFBFBD>
|
|
|
|
|
|
{
|
|
|
|
|
|
if(nIndex < 0 || nIndex >= m_skeletonLines.size())
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
SKLINE* line = &m_skeletonLines[nIndex];
|
|
|
|
|
|
if(line->size() < 2)
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
GPline* curve = new GPline();
|
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
SKLINE::iterator iter;
|
|
|
|
|
|
for(iter = line->begin(); iter != line->end(); iter ++ )
|
|
|
|
|
|
{
|
|
|
|
|
|
curve->AddPoint(GPoint3D(iter->x0, iter->y0,0));
|
|
|
|
|
|
//curve->x[count] = iter->x0;
|
|
|
|
|
|
//curve->y[count] = iter->y0;
|
|
|
|
|
|
//count ++ ;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double removeStep = 0.0001;
|
|
|
|
|
|
curve->RemoveSamePoint(removeStep);
|
|
|
|
|
|
if(curve->GetCount() < 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
delete curve;
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
// curve->GetLocation();
|
|
|
|
|
|
return curve;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//<2F><><EFBFBD>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
int GPlineSkeleton::GetSkeletonCurves(std::vector<GPline*>& curveVec)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_skeletonLines.empty() )
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
SKLINE::iterator iter;
|
|
|
|
|
|
for(int i = 0; i < m_skeletonLines.size(); i ++ )
|
|
|
|
|
|
{
|
|
|
|
|
|
GPline* curve = CreateSkeletonCurve(i);
|
|
|
|
|
|
if(curve == NULL)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
curveVec.push_back(curve);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return curveVec.size();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEB3A4><EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD><DFA3><EFBFBD><EFBFBD><EFBFBD>ΪGPlineָ<65>룬<EFBFBD><EBA3AC>Ҫ<EFBFBD>ⲿɾ<E2B2BF><C9BE>
|
|
|
|
|
|
GPline* GPlineSkeleton::CreateLongestCurve()
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_skeletonLines.empty() )
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
int nFindIndex = -1;
|
|
|
|
|
|
double dLength = 0;
|
|
|
|
|
|
double curLen;
|
|
|
|
|
|
|
|
|
|
|
|
SKLINE::iterator iter;
|
|
|
|
|
|
SKLINE::iterator prev;
|
|
|
|
|
|
for(int i = 0; i < m_skeletonLines.size(); i ++ )
|
|
|
|
|
|
{
|
|
|
|
|
|
SKLINE* line = &m_skeletonLines[i];
|
|
|
|
|
|
if(line->size() < 2)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
//<2F><><EFBFBD>õ<EFBFBD>ǰ<EFBFBD>ߵ<EFBFBD><DFB5><EFBFBD><EFBFBD>߳<EFBFBD><DFB3><EFBFBD>
|
|
|
|
|
|
curLen = 0;
|
|
|
|
|
|
prev = line->begin();
|
|
|
|
|
|
iter = prev;
|
|
|
|
|
|
iter++;
|
|
|
|
|
|
for(; iter != line->end(); iter ++ )
|
|
|
|
|
|
{
|
|
|
|
|
|
curLen += AfxGetBaseFunction()->Distance(prev->x0, prev->y0, iter->x0, iter->y0);
|
|
|
|
|
|
prev = iter;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//<2F>Ƚϻ<C8BD><CFBB><EFBFBD><EFBFBD><EFBFBD><EEB3A4>
|
|
|
|
|
|
if(nFindIndex < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
nFindIndex = i;
|
|
|
|
|
|
dLength = curLen;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if(dLength < curLen)
|
|
|
|
|
|
{
|
|
|
|
|
|
dLength = curLen;
|
|
|
|
|
|
nFindIndex = i;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return CreateSkeletonCurve(nFindIndex);
|
|
|
|
|
|
}
|