Click here to Skip to main content
15,891,136 members
Articles / Multimedia / GDI

Curve representation by ICAS (Inner Centered Arcs)

Rate me:
Please Sign up or sign in to vote.
4.80/5 (13 votes)
13 Nov 2011CPOL7 min read 30.2K   1.7K   25  
Suggestion about another curve representation
#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;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Japan Japan
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions