#include "stdafx.h"
#include "ICAS.h"
#include "IcasFig.h"
/////////////////////////////////////////////////////////////////////////////
// CIcas
//
#ifndef NO_MS_ENVIRONMENT
IMPLEMENT_SERIAL(CIcas, CObject, 0)
#endif
CIcas::CIcas()
{
m_Type = 0;
m_Reso = 0;
m_iD = -1;
m_iDL = -1;
m_iDR = -1;
m_iT = -1;
m_iTL = -1;
m_iTR = -1;
m_iTLL = -1;
m_iTRR = -1;
m_SegCnt = 0;
m_TriCnt = 0;
m_Tri = new ICASTRI[ L_ICAS_MAX ];
m_Seg = new ICASPOINT[ L_ICAS_MAX ];
m_iCur = 0;
m_dParam = 0.0;
m_dReso = 5.0;
}
CIcas::~CIcas()
{
if (m_Seg) delete m_Seg;
if (m_Tri) delete m_Tri;
}
#ifndef NO_MS_ENVIRONMENT
void CIcas::Serialize(CArchive& ar)
{
DWORD w;
if (ar.IsStoring())
{
w = (DWORD)m_Type; ar << w;
w = (DWORD)m_Reso; ar << w;
w = (DWORD)m_SegCnt; ar << w;
w = (DWORD)m_TriCnt; ar << w;
ar << m_dParam;
ar << m_dReso;
//Seg
for(int i=0; i<m_SegCnt; ++i)
{
w = (DWORD)m_Seg[i].typ;
ar << w;
ar << m_Seg[i].x;
ar << m_Seg[i].y;
}
//Tri
for(int k=0; k<m_TriCnt; ++k)
{
w = (DWORD)m_Tri[k].Typ;
ar << w;
for(int j=0; j<3; ++j)
{
w = (WORD)m_Tri[k].P[j].typ;
ar << w;
ar << m_Tri[k].P[j].x;
ar << m_Tri[k].P[j].y;
}
}
}
else
{
ar >> w; m_Type = w;
ar >> w; m_Reso = w;
ar >> w; m_SegCnt = w;
ar >> w; m_TriCnt = w;
ar >> m_dParam;
ar >> m_dReso;
//Seg
for(int i=0; i<m_SegCnt; ++i)
{
ar >> w;
m_Seg[i].typ = w;
ar >> m_Seg[i].x;
ar >> m_Seg[i].y;
}
//Tri
for(int k=0; k<m_TriCnt; ++k)
{
ar >> w;
m_Tri[k].Typ = w;
for(int j=0; j<3; ++j)
{
ar >> w;
m_Tri[k].P[j].typ = w;
ar >> m_Tri[k].P[j].x;
ar >> m_Tri[k].P[j].y;
}
}
}
}
#endif
//Draw Curve
int CIcas::Curve( int iT )
{
return IcasCurve( &(m_Tri[iT]), m_Type, m_Reso, m_dReso );
}
//Set Control Points
BOOL CIcas::SetCntl()
{
return IcasSetCntl( (m_Type & L_CLOSE), m_Seg, &m_SegCnt, m_Tri, &m_TriCnt );
}
#define L_HITMARGIN 3
BOOL CIcas::HitCntlPoint(CPoint &C)
{
int siz = m_TriCnt;
if (siz <= 0) return FALSE;
int iT, iTL, iTR;
BOOL sts = FALSE;
int x,y,lno,rno;
int r = C.x + L_HITMARGIN;
int l = C.x - L_HITMARGIN;
int t = C.y + L_HITMARGIN;
int b = C.y - L_HITMARGIN;
m_iD = -1;//Data Point
m_iT = -1;//Triangle
m_iTL = -1;//Left Triangle
m_iTR = -1;//Right Triangle
m_iDL = -1;
m_iDR = -1;
m_iTLL = -1;
m_iTRR = -1;
for(int i=0; i<siz; ++i)
{
//if ( !(m_Type & L_CLOSE) && (m_Tri[i].Typ & L_BRIDGE) ) {
// continue;
//}
if (m_Tri[i].Typ & L_IDENTDIR) continue;
//P[1]:Control point
x = (int)(m_Tri[i].P[1].x) ;
y = (int)(m_Tri[i].P[1].y) ;
if (x<l) continue;
else if (r<x) continue;
if (y>t) continue;
else if (b>y) continue;
iT = i;
m_bT = TRUE;
sts = TRUE;
//check pre & post Tri
lno = i-1;
rno = i+1;
if (0 == i) {
lno = siz-1;
}
else if (siz-1 == i) {
rno = 0;
}
if (m_Tri[lno].Typ & L_IDENTDIR) iTL = -1;
else iTL = lno;
if (m_Tri[rno].Typ & L_IDENTDIR) iTR = -1;
else iTR = rno;
break;
}
//undo-redo/reserve index & value
if (sts)
{
m_iT = iT;
m_T = m_Tri[iT];
if (iTL > -1) {
m_iTL = iTL;
m_TL = m_Tri[iTL];
}
if (iTR > -1) {
m_iTR = iTR;
m_TR = m_Tri[iTR];
}
}
return sts;
}
BOOL CIcas::HitAutoPoint(CPoint &C)
{
int siz = m_TriCnt;
if (siz <= 0) return FALSE;
BOOL sts = FALSE;
int x,y,rno;
int r = C.x + L_HITMARGIN;
int l = C.x - L_HITMARGIN;
int t = C.y + L_HITMARGIN;
int b = C.y - L_HITMARGIN;
m_iD = -1;//Data Point
m_iTL = -1;//Left Triangle
m_iDL = -1;
m_iDR = -1;
m_iTLL = -1;
m_iTRR = -1;
for(int i=0; i<siz; ++i)
{
if (!(m_Tri[i].Typ & L_AUTO_R)) continue;
//if ( !(m_Type & L_CLOSE) && (m_Tri[i].Typ & L_BRIDGE) ) {
// continue;
//}
//P[2]: point
x = (int)(m_Tri[i].P[2].x) ;
y = (int)(m_Tri[i].P[2].y) ;
if (x<l) continue;
else if (r<x) continue;
if (y>t) continue;
else if (b>y) continue;
//check post Tri
rno = i+1;
if (siz-1 == i) {
rno = 0;
}
if (m_Tri[rno].Typ & L_AUTO_L) {
m_iT = i;
m_iTR = rno;
m_bT = TRUE;
sts = TRUE;
break;
}
}
//undo-redo/reserve index & value
if (sts)
{
m_T = m_Tri[m_iT];
m_TR = m_Tri[m_iTR];
}
return sts;
}
BOOL CIcas::HitDataPoint(CPoint &C)
{
int dsiz = m_SegCnt;
int tsiz = m_TriCnt;
if (dsiz <= 0 || tsiz <= 0) return FALSE;
int iD=-1, iTL=-1, iTR=-1;
int x, y, ex, ey, lno=-1;
BOOL sts = FALSE;
int r = C.x + L_HITMARGIN;
int l = C.x - L_HITMARGIN;
int t = C.y + L_HITMARGIN;
int b = C.y - L_HITMARGIN;
m_iD = -1;//Data Point
m_iT = -1;//Triangle
m_iTL = -1;//Left Triangle
m_iTR = -1;//Right Triangle
m_iDL = -1;//Left Data Point
m_iDR = -1;//Right Data Point
m_iTLL = -1;
m_iTRR = -1;
for(int i=0; i<dsiz; ++i)
{
x = (int)(m_Seg[i].x) ;
y = (int)(m_Seg[i].y) ;
if (x<l) continue;
else if (r<x) continue;
if (y>t) continue;
else if (b>y) continue;
iD = i;
sts = TRUE;
break;
}
if (!sts) return sts;
//check pre & post Tri
for(int j=0; j<tsiz; ++j)
{
ex = (int)(m_Tri[j].P[2].x) ;
ey = (int)(m_Tri[j].P[2].y) ;
if (ex<l) continue;
else if (r<ex) continue;
if (ey>t) continue;
else if (b>ey) continue;
lno = j;
sts = TRUE;
break;
}
//undo-redo/reserve index & value
if (sts)
{
if (iD > -1)
{
m_iD = iD;//Data Point
m_D = m_Seg[iD];
}
if (lno > -1)
{
iTL = lno;
if (lno+1 >= tsiz) {
iTR = 0;
}
else iTR = lno+1;
if (!(m_Type & L_CLOSE)) //open
{
if (0 == iD) iTL = -1;
else if (tsiz-1 == iD) iTR = -1;
}
}
if (iTL > -1) {
m_iTL = iTL;
m_TL = m_Tri[iTL];
m_iDL = LeftSideData(m_iD);
if (m_Tri[iTL].Typ & L_AUTO_L) {
m_iTLL = LeftSideTri(iTL);
}
}
if (iTR > -1) {
m_iTR = iTR;
m_TR = m_Tri[iTR];
m_iDR = RightSideData(m_iD);
if (m_Tri[iTR].Typ & L_AUTO_R) {
m_iTRR = RightSideTri(iTR);
}
}
}
return sts;
}
BOOL CIcas::HitDataSeg(CPoint &C)
{
int dsiz = m_SegCnt;
int tsiz = m_TriCnt;
if (dsiz <= 0 || tsiz <= 0) return FALSE;
double x,y,sx,sy;
double r = (double)(C.x + L_HITMARGIN);
double l = (double)(C.x - L_HITMARGIN);
double t = (double)(C.y + L_HITMARGIN);
double b = (double)(C.y - L_HITMARGIN);
m_bDS = FALSE;
m_iDS = dsiz -1;
sx = m_Seg[m_iDS].x;
sy = m_Seg[m_iDS].y;
for(int i=0; i<dsiz; ++i)
{
x = m_Seg[i].x ;
y = m_Seg[i].y ;
m_iDE = i;
if ( CSClip(&sx, &sy, &x, &y, &l, &r, &t, &b ) ) {
m_bDS = TRUE;
//get corresponding triangle
m_bT = FALSE;
for(int j=0; j<tsiz; ++j)
{
if ( fabs(m_Tri[j].P[0].x - sx) < EPS
&& fabs(m_Tri[j].P[0].y - sy) < EPS
&& fabs(m_Tri[j].P[2].x - x) < EPS
&& fabs(m_Tri[j].P[2].y - y) < EPS )
{
m_bT = TRUE;
m_iT = j;
break;
}
}
return TRUE;
}
m_iDS = m_iDE;
sx = x;
sy = y;
}
return FALSE;
}
//
BOOL CIcas::HitTri(CPoint &C)
{
ICASPOINT Q;
int i,tsiz = m_TriCnt;
if (tsiz <= 0) return FALSE;
Q.x = (double)C.x;
Q.y = (double)C.y;
double r = (double)(C.x + L_HITMARGIN);
double l = (double)(C.x - L_HITMARGIN);
double t = (double)(C.y + L_HITMARGIN);
double b = (double)(C.y - L_HITMARGIN);
m_bT = FALSE;
for(i=0; i<tsiz; ++i)
{
//if ( !(m_Type & L_CLOSE) && (m_Tri[i].Typ & L_BRIDGE) ) {
// continue;
//}
if ( TriInsideChk( m_Tri[i].P, &Q ) )
{
m_bT = TRUE;
break;
}
if ( CSClip(&(m_Tri[i].P[0].x), &(m_Tri[i].P[0].y),
&(m_Tri[i].P[2].x), &(m_Tri[i].P[2].y), &l, &r, &t, &b ) )
{
m_bT = TRUE;
break;
}
}
//triangle found
if (m_bT)
{
int Typ = m_Tri[i].Typ;
m_iT = i;
m_Tri[i].Typ |= L_SELECTED;
//
if (Typ & L_AUTO_L) {
int iTL = m_iT - 1;
if (iTL < 0) {
iTL = m_TriCnt -1;//to end point
}
//
if (m_Tri[iTL].Typ & L_AUTO_R) {
m_Tri[iTL].Typ |= L_SELECTED;
}
}
if (Typ & L_AUTO_R) {
int iTR = m_iT + 1;
if (iTR > m_TriCnt -1 ) {
iTR = 0;//to start point
}
//
if (m_Tri[iTR].Typ & L_AUTO_L) {
m_Tri[iTR].Typ |= L_SELECTED;
}
}
}
return m_bT;
}
//
BOOL CIcas::GetPoint(ICASPOINT &P)
{
ICASTRI T;
double t = m_dParam;//parameter
double s = 0.5;
double tt;
double max = (double)m_TriCnt;
int ith = (int)t; //m_Tri[ ith ]
int imax = m_TriCnt;
//Bridge path over hang
if (!(m_Type & L_CLOSE)) {
max -= 1.0;
--imax;
}
if (ith == imax) {
--ith;
}
if (ith < 0 || imax <= ith) return FALSE;//-1;
if ( t < -EPS || (max + EPS) < t) return FALSE;//-2;
T = m_Tri[ ith ];
tt = t - (double)ith;//0.0 <= g_t < 1.0
P = *GetParametricPoint(&T, tt);
return TRUE;
}
//undo-redo
BOOL CIcas::Undo()
{
ICASPOINT wD;
ICASTRI wT;
BOOL sts = FALSE;
//switch values between variable & reserve
//Triangle
if (m_iT > -1) {
wT = m_Tri[m_iT];
m_Tri[m_iT] = m_T;
m_T = wT;
if (m_iTL > -1) {
wT = m_Tri[m_iTL];
m_Tri[m_iTL] = m_TL;
m_TL = wT;
}
if (m_iTR > -1) {
wT = m_Tri[m_iTR];
m_Tri[m_iTR] = m_TR;
m_TR = wT;
}
sts = TRUE;
}
//Segment Data
else if (m_iD > -1) {
wD = m_Seg[m_iD];
m_Seg[m_iD] = m_D;
m_D = wD;
//Triangle
if (m_iTL > -1) {
wT = m_Tri[m_iTL];
m_Tri[m_iTL] = m_TL;
m_TL = wT;
//
if (m_iTLL > 0 && (m_Tri[m_iTL].Typ & L_AUTO_L))
{
wT = m_Tri[m_iTLL];
m_Tri[m_iTLL] = m_TLL;
m_TLL = wT;
}
}
if (m_iTR > -1) {
wT = m_Tri[m_iTR];
m_Tri[m_iTR] = m_TR;
m_TR = wT;
//
if (m_iTRR > 0 && (m_Tri[m_iTR].Typ & L_AUTO_R))
{
wT = m_Tri[m_iTRR];
m_Tri[m_iTRR] = m_TRR;
m_TRR = wT;
}
}
sts = TRUE;
}
return sts;
}
//transformation for dragging period
BOOL CIcas::DragCntlPoint(ICASPOINT &D1)
{
m_Tri[m_iT].P[1] = D1;//dragging point
//reform left side triangle
if (!(m_Tri[m_iT].Typ & L_MLTSTART)) {//not link
if (-1 != m_iTL) {
//if (!(m_Type & L_CLOSE) && (m_Tri[m_iTL].Typ & L_BRIDGE));
//if (!(m_Type & L_CLOSE) && (m_iTL > m_iT));
//else GetSideTri(&(m_Tri[m_iTL]), &D1, 0);
GetSideTri(&(m_Tri[m_iTL]), &D1, 0);
}
}
//reform right side triangle
if (!(m_Tri[m_iT].Typ & L_MLTEND)) {//not link
if (-1 != m_iTR ) {
//if (!(m_Type & L_CLOSE) && (m_Tri[m_iTR].Typ & L_BRIDGE));
//if (!(m_Type & L_CLOSE) && (m_iTR < m_iT));
//else GetSideTri(&(m_Tri[m_iTR]), &D1, 1);
GetSideTri(&(m_Tri[m_iTR]), &D1, 1);
}
}
return TRUE;
}
//transformation for dragging period
BOOL CIcas::DragDataPoint(ICASPOINT &D1)
{
ICASPOINT C1,D2,C2,PX;
int sts = ChkLinearity(D1);//m_Seg[m_iD] = D1;//check for dragging point
if ( (L_PARALLEL | L_MULTIPLE) & sts ) {
//TRACE("ChkLinearity:SetCntl()\n");
SetCntl();
return TRUE;
}
//reform left side triangle
if (-1 != m_iTL) {
//if (!(m_Type & L_CLOSE) && (m_Tri[m_iTL].Typ & L_BRIDGE));
//if (!(m_Type & L_CLOSE) && (m_iD == 0));
//else {
GetSideTri2(&(m_Tri[m_iTL]), &D1, 0);
//curve crossing segment
if (m_iTLL > -1 && (m_Tri[m_iTLL].Typ & L_AUTO_R))
{
D2 = m_Seg[m_iDL ];
C1 = m_Tri[m_iTL ].P[1];
C2 = m_Tri[m_iTLL].P[1];
//reform cross point
GetCross(&D1, &D2, &C1, &C2, &PX);
m_Tri[m_iTL ].P[0] = PX;
m_Tri[m_iTLL].P[2] = PX;
}
//}
}
//reform right side triangle
if (-1 != m_iTR ) {
//if (!(m_Type & L_CLOSE) && (m_Tri[m_iTR].Typ & L_BRIDGE));
//if (!(m_Type & L_CLOSE) && (m_iD == m_SegCnt-1));
//else {
GetSideTri2(&(m_Tri[m_iTR]), &D1, 1);
//curve crossing segment
if (m_iTRR > -1 && (m_Tri[m_iTRR].Typ & L_AUTO_L))
{
D2 = m_Seg[m_iDR ];
C1 = m_Tri[m_iTR ].P[1];
C2 = m_Tri[m_iTRR].P[1];
//reform cross point
GetCross(&D1, &D2, &C1, &C2, &PX);
m_Tri[m_iTR ].P[2] = PX;
m_Tri[m_iTRR].P[0] = PX;
}
//}
}
return TRUE;
}
BOOL CIcas::DragAutoPoint(ICASPOINT &D1, int init)
{
ICASPOINT C,P,Q;
if (m_iT < 0 || m_iTR < 0) return FALSE;
if (init) {
return MoveVirtualPoint(m_Tri,m_TriCnt,m_iT,m_iTR,
&C,&P,&Q, &D1, 1);
}
else if (MoveVirtualPoint(m_Tri,m_TriCnt,m_iT,m_iTR,
&C,&P,&Q, &D1, 0))
{
m_Tri[m_iT ].P[1] = P;
m_Tri[m_iT ].P[2] = C;
m_Tri[m_iTR].P[0] = C;
m_Tri[m_iTR].P[1] = Q;
return TRUE;
}
return FALSE;
}
BOOL CIcas::DragIcasRecord(ICASPOINT &D1)
{
return MoveRecord(m_Tri,m_TriCnt,m_Seg,m_SegCnt,&D1);
}
BOOL CIcas::RotateIcasRecord(ICASPOINT &D1, int init)
{
return RotateRecord(m_Tri,m_TriCnt,m_Seg,m_SegCnt,m_iD,&D1,init);
}
BOOL CIcas::HitInArea(CPoint &C)
{
ICASPOINT O;
O.x = (double)C.x;
O.y = (double)C.y;
return ChkArea(m_Seg, m_SegCnt, &O );
}
BOOL CIcas::InsertAt(int idx, ICASPOINT &P)
{
if (idx < 0 || L_ICAS_MAX <= idx
|| m_SegCnt>= L_ICAS_MAX) return FALSE;
for(int i=m_SegCnt; i>idx; --i)
{
m_Seg[i] = m_Seg[i-1];
}
m_Seg[idx] = P;
m_SegCnt++;
//
return TRUE;
}
BOOL CIcas::DeleteAt(int idx)
{
if (idx < 0 || L_ICAS_MAX <= idx) return FALSE;
for(int i=idx; i<m_SegCnt; ++i)
{
m_Seg[i] = m_Seg[i+1];
}
m_SegCnt--;
//
return TRUE;
}
BOOL CIcas::InsertTri(int iT, ICASPOINT &I, ICASPOINT &SS, ICASPOINT &EE)
{
if (iT < 0 || m_TriCnt <= iT || m_TriCnt>= L_ICAS_MAX) return FALSE;
for(int i=m_TriCnt; i>iT; --i)
{
m_Tri[i] = m_Tri[i-1];
}
m_Tri[iT ].P[1] = SS;
m_Tri[iT ].P[2] = I;
//
m_Tri[iT+1].P[0] = I;
m_Tri[iT+1].P[1] = EE;
m_TriCnt++;
return TRUE;
}
BOOL CIcas::InsertTri2(int iT, ICASPOINT &I, ICASPOINT &SS, ICASPOINT &EE,
ICASPOINT &I2, ICASPOINT &SS2, ICASPOINT &EE2)
{
if (iT < 1 || m_TriCnt <= iT || m_TriCnt>= L_ICAS_MAX) return FALSE;
for(int i=m_TriCnt+1; i>iT; --i)
{
m_Tri[i] = m_Tri[i-2];
}
m_Tri[iT+2] = m_Tri[iT];
m_Tri[iT+1] = m_Tri[iT];
m_Tri[iT ] = m_Tri[iT-1];
//edit m_Tri[iT-1]
m_Tri[iT-1].Typ ^= L_AUTO_R;
m_Tri[iT-1].P[1] = SS2;
m_Tri[iT-1].P[2] = I2;
//edit m_Tri[iT]
m_Tri[iT ].P[0] = I2;
m_Tri[iT ].P[1] = EE2;
//edit m_Tri[iT+1]
m_Tri[iT+1].P[1] = SS;
m_Tri[iT+1].P[2] = I;
//edit m_Tri[iT+2]
m_Tri[iT+2].Typ ^= L_AUTO_L;
m_Tri[iT+2].P[0] = I;
m_Tri[iT+2].P[1] = EE;
//
m_TriCnt+=2;
return TRUE;
}
BOOL CIcas::CopySegMid()
{
if (m_bDS) {
if (m_iDS < 0 || L_ICAS_MAX <= m_iDS ) return FALSE;
if (m_iDE < 0 || L_ICAS_MAX <= m_iDE ) return FALSE;
//
ICASPOINT M;
MidPoint(m_Seg, m_iDS, m_iDE, &M);
//
InsertAt(m_iDE, M);
SetCntl();
}
return TRUE;
}
BOOL CIcas::CopyInnerCenter()
{
if (m_bT) {
if (m_iT < 0 || m_TriCnt <= m_iT) return FALSE;
ICASPOINT SS,EE,I;
ICASTRI T = m_Tri[m_iT];
//search triangle starting SegPoint
for(int i=0; i<m_SegCnt; ++i)
{
if (T.Typ & L_AUTO_R)
{
if ( fabs(T.P[0].x - m_Seg[i].x) < EPS
&& fabs(T.P[0].y - m_Seg[i].y) < EPS )
{
ICASPOINT SS2,EE2,I2;
ICASTRI T2 = m_Tri[m_iT+1];
if (!(T2.Typ & L_AUTO_L)) return FALSE;
GetInC(&(T.P[0]),&(T.P[2]),&(T.P[1]),&SS,&EE,&I,NULL,NULL);//L_AUTO_R
GetInC(&(T2.P[0]),&(T2.P[2]),&(T2.P[1]),&SS2,&EE2,&I2,NULL,NULL);//L_AUTO_L
InsertAt( i+1, I );
InsertAt( i+2, I2 );
InsertTri2( m_iT+1, I2, SS2, EE2, I, SS, EE);
return TRUE;
}
}
else {
if ( fabs(T.P[2].x - m_Seg[i].x) < EPS
&& fabs(T.P[2].y - m_Seg[i].y) < EPS )
{
if (T.Typ & L_AUTO_L) //add two InC
{
ICASPOINT SS2,EE2,I2;
ICASTRI T2 = m_Tri[m_iT-1];
if (!(T2.Typ & L_AUTO_R)) return FALSE;
GetInC(&(T2.P[0]),&(T2.P[2]),&(T2.P[1]),&SS2,&EE2,&I2,NULL,NULL);//L_AUTO_R
GetInC(&(T.P[0]),&(T.P[2]),&(T.P[1]),&SS,&EE,&I,NULL,NULL);//L_AUTO_L
InsertAt( i, I2 );
InsertAt( i+1, I );
InsertTri2( m_iT, I, SS, EE, I2, SS2, EE2);
}
else {//add one InC
GetInC(&(T.P[0]),&(T.P[2]),&(T.P[1]),&SS,&EE,&I,NULL,NULL);
InsertAt( i, I );
InsertTri( m_iT, I, SS, EE);
}
return TRUE;
}
}
}
}
return FALSE;
}
//
BOOL CIcas::ChkDeletePoint()
{
int iTR=m_iTR, iTL=m_iTL, delcnt = 1;
int dst,src,edt,flg=0;
ICASTRI T;
if (m_SegCnt <= 3) return FALSE;
if (m_iD < 0 || m_SegCnt <= m_iD) return FALSE;
if (iTL < 0 || iTR < 0) return FALSE;
if (m_Tri[iTL].Typ & L_AUTO_L) {
iTL = LeftSideTri(iTL);
++delcnt;
//TRACE("AUTO_L:delcnt=%d\n",delcnt);
flg |= 0x1;
}
iTL = LeftSideTri(iTL);
if (m_Tri[iTR].Typ & L_AUTO_R) {
iTR = RightSideTri(iTR);
++delcnt;
//TRACE("AUTO_R:delcnt=%d\n",delcnt);
flg |= 0x2;
}
iTR = RightSideTri(iTR);
//TRACE("iTL=%d,iTR=%d,delcnt=%d\n",iTL,iTR,delcnt);
//
T.P[0] = m_Seg[m_iDL];
T.P[1] = m_Seg[m_iD];//Data point -> Control point
T.P[2] = m_Seg[m_iDR];
T.Typ = (L_NORMAL | L_MLTSTART | L_MLTEND);
m_Tri[iTL].Typ |= L_MLTEND;
m_Tri[iTR].Typ |= L_MLTSTART;
edt = (iTL + 1)%m_TriCnt;
if (0 == m_iD) {
dst = 0;
T.Typ |= L_BRIDGE;
edt = m_TriCnt - delcnt;
--edt;//last for edit
//if (flg&0x1) {
if (flg&0x2) src = 2;
else src = 1;
//}
//else {
// if (flg&0x2) src = 2;
// else src = 1;
//}
}
else {
if (iTR-delcnt<0) src = m_TriCnt;//nop
else src = iTR;
dst = iTR - delcnt;
}
//TRACE("dst=%d,src=%d,edt=%d\n",dst,src,edt);
//m_iTR -> delcnt del
for(int i=src; i<m_TriCnt; ++i)
{
m_Tri[dst] = m_Tri[i];
++dst;
}
m_TriCnt -= delcnt;
m_Tri[edt] = T;
//m_iD del
DeleteAt(m_iD);
m_iD = -1;
return TRUE;
}
BOOL CIcas::DeleteTri(int iT, ICASPOINT &C)
{
if (iT < 0 || m_TriCnt < iT) return FALSE;
m_Tri[iT+1].P[0] = m_Tri[iT].P[0];
m_Tri[iT+1].P[1] = C;
for(int i=iT; i<m_TriCnt; ++i)
{
m_Tri[i] = m_Tri[i+1];
}
m_TriCnt--;
return TRUE;
}
//Control point Operations
BOOL CIcas::DeleteCntl()
{
if (!m_bT) return FALSE;
if (m_iT < 0 || m_TriCnt <= m_iT) return FALSE;
int iTL, iTR;
if (!BothSideTri(m_iT, iTL, iTR)) return FALSE;
if (m_Tri[m_iT].Typ & L_AUTO_L)
{
if (m_Tri[iTL].Typ & L_AUTO_R)//change front Tri
{
m_Tri[iTL].Typ ^= L_AUTO_R;
m_Tri[iTL].Typ |= L_MLTEND;
m_Tri[iTL].P[2] = m_Tri[m_iT].P[2];//delete m_iT
//
if (!(m_Type & L_CLOSE)&&(m_Tri[iTR].Typ & L_BRIDGE));//nop
else m_Tri[iTR].Typ |= L_MLTSTART;
}
else return FALSE;
}
else if (m_Tri[m_iT].Typ & L_AUTO_R)
{
if (m_Tri[iTR].Typ & L_AUTO_L)//change rear Tri
{
m_Tri[iTR].Typ ^= L_AUTO_L;
m_Tri[iTR].Typ |= L_MLTSTART;
m_Tri[iTR].P[0] = m_Tri[m_iT].P[0];//delete m_iT
//
if (!(m_Type & L_CLOSE)&&(m_Tri[iTL].Typ & L_BRIDGE));//nop
else m_Tri[iTL].Typ |= L_MLTEND;
}
else return FALSE;
}
else return FALSE;
//delete m_Tri[m_iT]
for(int i=m_iT; i<m_TriCnt; ++i)
{
m_Tri[i] = m_Tri[i+1];
}
m_TriCnt--;
m_bT = FALSE;
return TRUE;
}
/**
BOOL CIcas::DeleteCntl()
{
if (!m_bT) return FALSE;
if (m_iT < 0 || m_TriCnt <= m_iT) return FALSE;
int iTL, iTR;
if (!BothSideTri(m_iT, iTL, iTR)) return FALSE;
if (m_Tri[m_iT].Typ & L_AUTO_L)
{
if (m_iT-1 < 0) return FALSE;//BUG
if (m_Tri[m_iT-1].Typ & L_AUTO_R)//change front Tri
{
m_Tri[m_iT-1].Typ ^= L_AUTO_R;
m_Tri[m_iT-1].Typ |= L_MLTEND;
m_Tri[m_iT-1].P[2] = m_Tri[m_iT].P[2];//delete m_iT
//
m_Tri[m_iT+1].Typ |= L_MLTSTART;
}
else return FALSE;
}
else if (m_Tri[m_iT].Typ & L_AUTO_R)
{
if (m_iT+1 >= m_TriCnt) return FALSE;//BUG
if (m_Tri[m_iT+1].Typ & L_AUTO_L)//change rear Tri
{
m_Tri[m_iT+1].Typ ^= L_AUTO_L;
m_Tri[m_iT+1].Typ |= L_MLTSTART;
m_Tri[m_iT+1].P[0] = m_Tri[m_iT].P[0];//delete m_iT
//
m_Tri[m_iT-1].Typ |= L_MLTEND;
}
else return FALSE;
}
else return FALSE;
//delete m_Tri[m_iT]
for(int i=m_iT; i<m_TriCnt; ++i)
{
m_Tri[i] = m_Tri[i+1];
}
m_TriCnt--;
m_bT = FALSE;
return TRUE;
}
/**/
BOOL CIcas::InsertCntl(int front)//front :0 add rear m_iT 1:add front m_iT
{
if (m_TriCnt>= L_ICAS_MAX) return FALSE;
int iTL, iTR;
if (!BothSideTri(m_iT, iTL, iTR)) return FALSE;
ICASPOINT M, C2;
CalcInsertCntl(m_Tri, m_iT, &M, &C2);
//make space //to be m_Tri[m_iT] == m_Tri[m_iT+1]
for(int i=m_TriCnt; i>m_iT; --i)
{
m_Tri[i] = m_Tri[i-1];
}
m_TriCnt++;
iTR++;
//insert m_Tri[m_iT] or m_Tri[m_iT+1]
if (front) {
//insert
m_Tri[m_iT ].P[2] = M;
m_Tri[m_iT ].P[1] = C2;
m_Tri[m_iT ].Typ |= (L_AUTO_R | L_MLTSTART);
//link edit
m_Tri[m_iT+1].P[0] = M;
m_Tri[m_iT+1].Typ |= L_AUTO_L;
//
if (!(m_Type & L_CLOSE)&&(m_Tri[iTL].Typ & L_BRIDGE));//nop
else m_Tri[iTL].Typ |= L_MLTEND;
}
else {
//insert
m_Tri[m_iT+1].P[1] = C2;
m_Tri[m_iT+1].P[0] = M;
m_Tri[m_iT+1].Typ |= (L_AUTO_L | L_MLTEND);
//link edit
m_Tri[m_iT ].P[2] = M;
m_Tri[m_iT ].Typ |= L_AUTO_R;
//
if (!(m_Type & L_CLOSE)&&(m_Tri[iTR].Typ & L_BRIDGE));//nop
else m_Tri[iTR].Typ |= L_MLTSTART;
}
m_bT = FALSE;
return TRUE;
}
/**
BOOL CIcas::InsertCntl(int front)//front :0 add rear m_iT 1:add front m_iT
{
if (m_iT < 0 || m_TriCnt <= m_iT || m_TriCnt>= L_ICAS_MAX) return FALSE;
ICASPOINT M, C2;
CalcInsertCntl(m_Tri, m_iT, &M, &C2);
//make space //to be m_Tri[m_iT] == m_Tri[m_iT+1]
for(int i=m_TriCnt; i>m_iT; --i)
{
m_Tri[i] = m_Tri[i-1];
}
m_TriCnt++;
//insert m_Tri[m_iT] or m_Tri[m_iT+1]
if (front) {
//insert
m_Tri[m_iT ].P[2] = M;
m_Tri[m_iT ].P[1] = C2;
m_Tri[m_iT ].Typ |= (L_AUTO_R | L_MLTSTART);
//link edit
m_Tri[m_iT+1].P[0] = M;
m_Tri[m_iT+1].Typ |= L_AUTO_L;
//
if (m_iT-1 >= 0) {//BUG
m_Tri[m_iT-1].Typ |= L_MLTEND;
}
}
else {
//insert
m_Tri[m_iT+1].P[1] = C2;
m_Tri[m_iT+1].P[0] = M;
m_Tri[m_iT+1].Typ |= (L_AUTO_L | L_MLTEND);
//link edit
m_Tri[m_iT ].P[2] = M;
m_Tri[m_iT ].Typ |= L_AUTO_R;
//
if (m_iT+2 < m_TriCnt) {//BUG
m_Tri[m_iT+2].Typ |= L_MLTSTART;
}
}
m_bT = FALSE;
return TRUE;
}
/**/
void CIcas::SelReset()
{
if (m_Type & L_SELECTED) {
m_Type ^= L_SELECTED;
}
for(int i=0; i<m_SegCnt; ++i)
{
if (m_Seg[i].typ & L_SELECTED) {
m_Seg[i].typ ^= L_SELECTED;
}
}
for(int j=0; j<m_TriCnt; ++j)
{
if (m_Tri[j].Typ & L_SELECTED) {
m_Tri[j].Typ ^= L_SELECTED;
}
}
}
//
int CIcas::ChkLinearity(ICASPOINT &D)
{
int sts = L_NORMAL;
//coordinate values only
m_Seg[m_iD].x = D.x;
m_Seg[m_iD].y = D.y;
//check original typ
if (m_Seg[m_iD].typ & L_MULTIPLE ) {
//TRACE("ChkLineality0A[%d]:%x\n",m_iD,m_Seg[m_iD].typ);
m_Seg[m_iD].typ ^= (L_NORMAL | L_MULTIPLE );
sts = L_MULTIPLE;
}
else if (m_Seg[m_iD].typ & L_PARALLEL) {
//TRACE("ChkLineality0B:[%d]%x\n",m_iD,m_Seg[m_iD].typ);
m_Seg[m_iD].typ ^= (L_NORMAL | L_PARALLEL);
sts = L_PARALLEL;
}
else {
if (!(m_Type & L_CLOSE) && ( (m_Tri[m_iTL].Typ & L_BRIDGE)
||(m_Tri[m_iTR].Typ & L_BRIDGE)));//nop
else {
sts = ChkLinear(m_Seg, m_iDL, m_iDR, &D);
}
}
//TRACE("ChkLineality4:%x\n",sts);
return sts;
}