#include "lib_modeling.h"
#include "ge_sort.h"

//////////////////////////////////////////////////////////////////////////

ModelingLib *lib_modeling = NULL;

static ModelingLib *CheckModelingLib(LONG offset)
{
	return (ModelingLib*)CheckLib(LIBRARY_MODELLING,offset,(C4DLibrary**)&lib_modeling);
}

#define ModelingLibCall(b) 		ModelingLib *lib = CheckModelingLib(LIBOFFSET(ModelingLib, b)); \
															if (!lib || !lib->b) return; \
															(((iModeling*)this)->*lib->b)

#define ModelingLibCallR(a,b)  ModelingLib *lib = CheckModelingLib(LIBOFFSET(ModelingLib, b)); \
															if (!lib || !lib->b) return a; \
															return (((iModeling*)this)->*lib->b)

Modeling* Modeling::Alloc()
{
	ModelingLib *lib = CheckModelingLib(LIBOFFSET(ModelingLib,Alloc)); if (!lib) return NULL;
	return (Modeling*)lib->Alloc();
}

void Modeling::Free(Modeling *&p)
{
	if (!p) return;
	ModelingLib *lib = CheckModelingLib(LIBOFFSET(ModelingLib,Free)); if (!lib) return;
	iModeling* i = (iModeling*)p;
	lib->Free(i);
	p = NULL;
}

//////////////////////////////////////////////////////////////////////////

Bool Modeling::InitArray(AtomArray *objs, LONG flags)
{
  ModelingLibCallR(FALSE,InitArray)(objs,flags);
}

Bool Modeling::InitObject(C4DAtom *op, LONG flags)
{
	ModelingLibCallR(FALSE,InitObject)(op,flags);
}

Bool Modeling::Commit(C4DAtom *op, LONG flags, BaseObject* cobj)
{
	ModelingLibCallR(FALSE,Commit)(op,flags,cobj);
}

void Modeling::Release()
{
	ModelingLibCall(Release)();
}

void  Modeling::ReleaseObject(C4DAtom *op)
{
	ModelingLibCall(ReleaseObject)(op);
}

LONG Modeling::AddPoint(C4DAtom *op, const Vector &p)
{
	ModelingLibCallR(0,AddPoint)(op,p);
}

LONG Modeling::ClonePoint(C4DAtom *op, LONG index)
{
	ModelingLibCallR(0,ClonePoint)(op,index);
}

Bool Modeling::DeletePoint(C4DAtom *op, LONG index)
{
	ModelingLibCallR(FALSE,DeletePoint)(op, index);
}

Bool Modeling::GetPoint(C4DAtom *op, LONG index, Vector *p)
{
	ModelingLibCallR(FALSE,GetPoint)(op,index,p);
}

Bool Modeling::SetPoint(C4DAtom *op, LONG index, const Vector &p, LONG flags)
{
	ModelingLibCallR(FALSE,SetPoint)(op,index,p,flags);
}

Bool Modeling::SetEdgePoint(C4DAtom *op, LONG index, Real l, LONG flags)
{
	ModelingLibCallR(FALSE,SetEdgePoint)(op,index,l,flags);
}

LONG Modeling::NewNgon(C4DAtom *op, LONG flags)
{
	ModelingLibCallR(0,NewNgon)(op,flags);
}

LONG Modeling::AddNgon(C4DAtom *op, const Ngon &ngon, LONG flags)
{
	ModelingLibCallR(0,AddNgon)(op,ngon,flags);
}

LONG Modeling::CreateNgon(C4DAtom *op, LONG *padr, LONG cnt, LONG flags)
{
	ModelingLibCallR(0,CreateNgon)(op,padr,cnt,flags);
}

Bool Modeling::DeleteNgon(C4DAtom *op, LONG index, Bool points)
{
	ModelingLibCallR(FALSE,DeleteNgon)(op,index,points);
}

LONG Modeling::CloneNgon(C4DAtom *op, LONG index, LONG flags)
{
	ModelingLibCallR(0,CloneNgon)(op,index,flags);
}

Bool Modeling::GetNgon(C4DAtom *op, LONG index, Ngon *ngon, LONG flags)
{
	ModelingLibCallR(FALSE,GetNgon)(op,index,ngon,flags);
}

Bool Modeling::SetNgon(C4DAtom *op, LONG index, Ngon &ngon, LONG flags)
{
	ModelingLibCallR(FALSE,SetNgon)(op,index,ngon,flags);
}

LONG Modeling::SplitEdge(C4DAtom *op, LONG p1, LONG p2, Real l)
{
	ModelingLibCallR(0,SplitEdge)(op,p1,p2,l);
}

Bool Modeling::DeleteEdge(C4DAtom *op, LONG index, LONG p1, LONG p2)
{
	ModelingLibCallR(FALSE,DeleteEdge)(op,index,p1,p2);
}

Bool Modeling::MeltEdgeBetween(C4DAtom *op, LONG pa, LONG pb, LONG p1, LONG p2)
{
	ModelingLibCallR(FALSE,MeltEdgeBetween)(op,pa,pb,p1,p2);
}

Bool Modeling::MeltEdge(C4DAtom *op, LONG pa, LONG p1, LONG p2)
{
	ModelingLibCallR(FALSE,MeltEdge)(op,pa,p1,p2);
}

Bool Modeling::MeltPoint(C4DAtom *op, LONG p)
{
	ModelingLibCallR(FALSE,MeltPoint)(op,p);
}

LONG Modeling::SplitPolygon(C4DAtom *op, LONG index, LONG p1, LONG p2)
{
	ModelingLibCallR(0,SplitPolygon)(op,index,p1,p2);
}

Bool Modeling::MergePolygons(C4DAtom *op, LONG pa, LONG pb)
{
	ModelingLibCallR(FALSE,MergePolygons)(op,pa,pb);
}

Bool Modeling::IsValidEdge(C4DAtom *op, LONG index, LONG p1, LONG p2)
{
	ModelingLibCallR(FALSE,IsValidEdge)(op,index,p1,p2);
}

Bool Modeling::IsValidNgon(C4DAtom *op, LONG index)
{
	ModelingLibCallR(FALSE,IsValidNgon)(op,index);
}

Bool Modeling::IsValidPoint(C4DAtom *op, LONG index)
{
	ModelingLibCallR(FALSE,IsValidPoint)(op,index);
}

LONG *Modeling::GetEdgeNgons(C4DAtom *op, LONG p1, LONG p2, LONG &pcnt)
{
	ModelingLibCallR(FALSE,GetEdgeNgons)(op,p1,p2,pcnt);
}

LONG *Modeling::GetPointNgons(C4DAtom *op, LONG p, LONG &pcnt, Bool clone)
{
	ModelingLibCallR(FALSE,GetPointNgons)(op,p,pcnt,clone);
}

LONG *Modeling::GetNeighborNgons(C4DAtom *op, LONG index, LONG &pcnt)
{
	ModelingLibCallR(FALSE,GetNeighborNgons)(op,index,pcnt);
}

LONG *Modeling::GetPointEdges(C4DAtom *op, LONG p, LONG &ecnt)
{
	ModelingLibCallR(FALSE,GetPointEdges)(op,p,ecnt);
}

Bool Modeling::GetOriginalEdgePoints(C4DAtom *op, LONG edge, LONG &p1, LONG &p2)
{
	ModelingLibCallR(FALSE,GetOriginalEdgePoints)(op,edge,p1,p2);
}

Bool Modeling::IsEdgeDeleted(C4DAtom *op, LONG p1, LONG p2)
{
	ModelingLibCallR(FALSE,IsEdgeDeleted)(op,p1,p2);
}

LONG Modeling::TranslateNgonIndex(C4DAtom *op, LONG index, Bool tovirtual)
{
	ModelingLibCallR(FALSE,TranslateNgonIndex)(op,index,tovirtual);
}

LONG Modeling::TranslatePointIndex(C4DAtom *op, LONG index, Bool tovirtual)
{
	ModelingLibCallR(FALSE,TranslatePointIndex)(op,index,tovirtual);
}

Bool Modeling::GetPointMap(C4DAtom *op, LONG **map, LONG *count)
{
	ModelingLibCallR(FALSE,GetPointMap)(op,map,count);
}

Bool Modeling::GetNgonMap(C4DAtom *op, LONG **map, LONG *count)
{
	ModelingLibCallR(FALSE,GetNgonMap)(op,map,count);
}

Bool Modeling::ReleaseMap(C4DAtom *op, LONG *map)
{
	ModelingLibCallR(FALSE,ReleaseMap)(op,map);
}

Bool Modeling::FreeMap(C4DAtom *op, LONG *map)
{
	ModelingLibCallR(FALSE,FreeMap)(op,map);
}

Bool Modeling::GetNgonNormal(C4DAtom *op, LONG index, Vector *n)
{
	ModelingLibCallR(FALSE,GetNgonNormal)(op,index,n);
}

Bool Modeling::FlipNgonNormal(C4DAtom *op, LONG index)
{
	ModelingLibCallR(FALSE,FlipNgonNormal)(op,index);
}

Bool Modeling::SetPoints(C4DAtom *op, PointMove *pnts, LONG cnt, Bool commit, LONG flags)
{
	ModelingLibCallR(FALSE,SetPoints)(op,pnts,cnt,commit,flags);
}

LONG Modeling::GetLastError(C4DAtom *op)
{
	ModelingLibCallR(FALSE,GetLastError)(op);
}

Bool Modeling::IsModified(C4DAtom *op)
{
	ModelingLibCallR(FALSE,IsModified)(op);
}

Bool Modeling::GetPointInfo(C4DAtom *op, LONG index, LONG &ia, LONG &ib, Real &t)
{
	ModelingLibCallR(FALSE,GetPointInfo)(op,index,ia,ib,t);
}

Bool Modeling::GetOriginPoint(C4DAtom *op, LONG index, LONG &ci)
{
	ModelingLibCallR(FALSE,GetOriginPoint)(op,index,ci);
}

Bool Modeling::GetOriginNgon(C4DAtom *op, LONG index, LONG &ci)
{
	ModelingLibCallR(FALSE,GetOriginNgon)(op,index,ci);
}

Bool Modeling::FindNgon(C4DAtom *op, LONG p1, LONG p2, LONG &index)
{
	ModelingLibCallR(FALSE,FindNgon)(op,p1,p2,index);
}

Bool Modeling::SetOriginNgon(C4DAtom *op, LONG index, LONG ci)
{
	ModelingLibCallR(FALSE,SetOriginNgon)(op,index,ci);
}

LONG Modeling::GetNgonFlags(C4DAtom *op, LONG index)
{
	ModelingLibCallR(FALSE,GetNgonFlags)(op,index);
}

LONG Modeling::SetNgonFlags(C4DAtom *op, LONG index, LONG flags)
{
	ModelingLibCallR(FALSE,SetNgonFlags)(op,index,flags);
}

Bool Modeling::SetPointInfo(C4DAtom *op, LONG index, LONG ia, LONG ib, Real t)
{
	ModelingLibCallR(FALSE,SetPointInfo)(op,index,ia,ib,t);
}

Bool Modeling::SetOriginPoint(C4DAtom *op, LONG index, LONG ci)
{
	ModelingLibCallR(FALSE,SetOriginPoint)(op,index,ci);
}

LONG Modeling::GetPointFlags(C4DAtom *op, LONG index)
{
	ModelingLibCallR(FALSE,GetPointFlags)(op,index);
}

LONG Modeling::SetPointFlags(C4DAtom *op, LONG index, LONG flags)
{
	ModelingLibCallR(FALSE,SetPointFlags)(op,index,flags);
}

Bool Modeling::GetPointOrigin(C4DAtom *op, LONG index, Vector &opnt)
{
	ModelingLibCallR(FALSE,GetPointOrigin)(op,index,opnt);
}

Bool Modeling::SetPointOrigin(C4DAtom *op, LONG index, Vector opnt, LONG flags)
{
	ModelingLibCallR(FALSE,SetPointOrigin)(op,index,opnt,flags);
}

Bool Modeling::SetInterPoint(C4DAtom *op, LONG index, Vector npnt, Real t, LONG flags)
{
	ModelingLibCallR(FALSE,SetInterPointBetween)(op,index,npnt,t,flags);
}

Bool Modeling::WeldPoints(C4DAtom *op, LONG source, LONG dest)
{
	ModelingLibCallR(FALSE,WeldPoints)(op,source,dest);
}

Bool Modeling::MeltNgon(C4DAtom *op, LONG pa)
{
	ModelingLibCallR(FALSE,MeltNgon)(op,pa);
}

Bool Modeling::GetFaceSelection(C4DAtom *op, BaseSelect *select, BaseSelect *faceselect, BaseSelect *hidden)
{
	ModelingLibCallR(FALSE,GetFaceSelection)(op,select,faceselect,hidden);
}

Bool Modeling::IsPointDeleted(C4DAtom *op, LONG index)
{
	ModelingLibCallR(FALSE,IsPointDeleted)(op,index);
}

Bool Modeling::IsFaceDeleted(C4DAtom *op, LONG index)
{
	ModelingLibCallR(FALSE,IsFaceDeleted)(op,index);
}

Bool Modeling::SetInterPoint(C4DAtom *op, LONG index, const Vector &move, const Vector &offset, LONG flags)
{
	ModelingLibCallR(FALSE,SetInterPointMove)(op,index,move,offset,flags);
}

Bool Modeling::GetEdgeSelection(C4DAtom *op, BaseSelect *select, BaseSelect *edgeselect, BaseSelect *hidden)
{
	ModelingLibCallR(FALSE,GetFaceSelection)(op,select,edgeselect,hidden);
}

LONG *Modeling::GetEdgeSelectionArray(C4DAtom *op, BaseSelect *select, LONG &ecnt, BaseSelect *hidden, Bool tovirtual)
{
	ModelingLibCallR(FALSE,GetEdgeSelectionArray)(op,select,ecnt,hidden,tovirtual);
}

Bool Modeling::InsertFacePoint(C4DAtom *op, LONG pa, LONG p1)
{
	ModelingLibCallR(FALSE,InsertFacePoint)(op,pa,p1);
}

Bool Modeling::CreateHole(C4DAtom *op, LONG index, const Ngon &ngon)
{
	ModelingLibCallR(FALSE,CreateHole)(op,index,ngon);
}

Bool Modeling::CreateHole(C4DAtom *op, LONG index, LONG *pnts, LONG pcnt)
{
	ModelingLibCallR(FALSE,CreateHoleFromPoints)(op,index,pnts,pcnt);
}

Bool Modeling::ResizeNgon(C4DAtom *op, LONG index, LONG pcnt, LONG scnt)
{
	ModelingLibCallR(FALSE,ResizeNgon)(op,index,pcnt,scnt);
}

Bool Modeling::GetEdgeSegment(C4DAtom *op, LONG pa, LONG p1, LONG p2, LONG *seg, LONG *s1, LONG *s2, Bool rel)
{
	ModelingLibCallR(FALSE,GetEdgeSegment)(op,pa,p1,p2,seg,s1,s2,rel);
}

void Modeling::FreeTable(C4DAtom *op, void *table)
{
	ModelingLibCall(FreeTable)(table);
}

Bool Modeling::PointInFace(C4DAtom *op, LONG index, const Vector &p)
{
	ModelingLibCallR(FALSE,PointInFace)(op,index,p);
}

Bool Modeling::PointInFace(C4DAtom *op, const Ngon &ngon, const Vector &p)
{
	ModelingLibCallR(FALSE,PointInFaceNgon)(op,ngon,p);
}

Bool Modeling::LineFaceIntersection(C4DAtom *op, LONG index, const Vector &p1, const Vector &p2)
{
	ModelingLibCallR(FALSE,LineFaceIntersection)(op,index,p1,p2);
}

Bool Modeling::LineFaceIntersection(C4DAtom *op, const Ngon &ngon, const Vector &p1, const Vector &p2)
{
	ModelingLibCallR(FALSE,LineFaceIntersectionNgon)(op,ngon,p1,p2);
}

void Modeling::SetTriangulateHook(C4DAtom *op, TriangulateHook pHook, void *pData)
{
	ModelingLibCall(SetTriangulateHook)(op,pHook,pData);
}

void Modeling::GetTriangulateHook(C4DAtom *op, TriangulateHook *ppHook, void **ppData)
{
	ModelingLibCall(GetTriangulateHook)(op,ppHook,ppData);
}

//////////////////////////////////////////////////////////////////////////

class TranslationMapSearch : public GeSortAndSearch
{
	virtual LONG Compare(void* a, void* b)
	{
		return ((TransIndexMapData*)a)->oIndex-((TransIndexMapData*)b)->oIndex;
	}
};

class TranslationMapSearchN : public GeSortAndSearch
{
	virtual LONG Compare(void* a, void* b)
	{
		return ((TransIndexMapData*)a)->nIndex-((TransIndexMapData*)b)->nIndex;
	}
};

class TranslationMapNewSearch : public GeSortAndSearch
{
	virtual LONG Compare(void* a, void* b)
	{
		return ((TransMapNewData*)a)->nIndex-((TransMapNewData*)b)->nIndex;
	}
};

LONG TranslationMaps::FindOriginalPoint(LONG index)
{
	if (!m_pPointMap) return NOTOK;

	TranslationMapSearch search;
	TransMapData key(index);

	TransMapData *found=(TransMapData*)search.Search(&key,m_pPointMap,m_mPointCount,sizeof(TransMapData));
	if (!found) return NOTOK;
	return found-m_pPointMap;
}

LONG TranslationMaps::FindOriginalPolygon(LONG index)
{
	if (!m_pPolygonMap) return NOTOK;

	TranslationMapSearch search;
	TransMapData key(index);

	TransMapData *found=(TransMapData*)search.Search(&key,m_pPolygonMap,m_mPolygonCount,sizeof(TransMapData));
	if (!found) return NOTOK;
	return found-m_pPolygonMap;
}

LONG TranslationMaps::FindOriginalPgon(LONG index)
{
	if (!m_pPgonMap) return NOTOK;

	TranslationMapSearch search;
	TransMapData key(index);

	TransMapData *found=(TransMapData*)search.Search(&key,m_pPgonMap,m_mPgonCount,sizeof(TransMapData));
	if (!found) return NOTOK;
	return found-m_pPgonMap;
}

LONG TranslationMaps::FindOriginalSegment(LONG index)
{
	if (!m_pSegmentMap) return NOTOK;

	TranslationMapSearch search;
	TransMapData key(index);

	TransMapData *found=(TransMapData*)search.Search(&key,m_pSegmentMap,m_mSegmentCount,sizeof(TransMapData));
	if (!found) return NOTOK;
	return found-m_pSegmentMap;
}

LONG TranslationMaps::FindNewPoint(LONG index)
{
	if (!m_pNewPointMap) return NOTOK;

	TranslationMapNewSearch search;
	TransMapNewData key(index);

	TransMapNewData *found=(TransMapNewData*)search.Search(&key,m_pNewPointMap,m_mPointCount,sizeof(TransMapNewData));
	if (!found) return NOTOK;
	return found-m_pNewPointMap;
}

LONG TranslationMaps::FindNewPolygon(LONG index)
{
	if (!m_pNewPolygonMap) return NOTOK;

	TranslationMapNewSearch search;
	TransMapNewData key(index);

	TransMapNewData *found=(TransMapNewData*)search.Search(&key,m_pNewPolygonMap,m_mPolygonCount,sizeof(TransMapNewData));
	if (!found) return NOTOK;
	return found-m_pNewPolygonMap;
}

LONG TranslationMaps::FindNewPgon(LONG index)
{
	if (!m_pNewPgonMap) return NOTOK;

	TranslationMapNewSearch search;
	TransMapNewData key(index);

	TransMapNewData *found=(TransMapNewData*)search.Search(&key,m_pNewPgonMap,m_mPgonCount,sizeof(TransMapNewData));
	if (!found) return NOTOK;
	return found-m_pNewPgonMap;
}

LONG TranslationMaps::FindNewSegment(LONG index)
{
	if (!m_pNewSegmentMap) return NOTOK;

	TranslationMapNewSearch search;
	TransMapNewData key(index);

	TransMapNewData *found=(TransMapNewData*)search.Search(&key,m_pNewSegmentMap,m_mSegmentCount,sizeof(TransMapNewData));
	if (!found) return NOTOK;
	return found-m_pNewSegmentMap;
}

LONG TranslationMaps::FindWeldPoint(LONG index)
{
	if (!m_pWeldMap) return NOTOK;

	TranslationMapSearchN search;
	TransIndexMapData key(-1,index);

	TransIndexMapData *found=(TransIndexMapData*)search.Search(&key,m_pWeldMap,m_mWeldCount,sizeof(TransIndexMapData));
	if (!found) return NOTOK;
	return found-m_pWeldMap;
}

LONG TranslationMaps::FindMeltPolygon(LONG index)
{
	if (!m_pMeltMap) return NOTOK;

	TranslationMapSearchN search;
	TransIndexMapData key(-1,index);

	TransIndexMapData *found=(TransIndexMapData*)search.Search(&key,m_pMeltMap,m_mMeltCount,sizeof(TransIndexMapData));
	if (!found) return NOTOK;
	return found-m_pMeltMap;
}
