#include "lib_ngon.h" #ifdef __API_INTERN__ #include "polygonobject.h" #include "basemath.h" #else #include "c4d_baseobject.h" #include "c4d_tools.h" #endif #include "c4d_general.h" Ngon::Ngon() { points=nullptr; segments=nullptr; count=0; segcount=0; } Ngon::~Ngon() { Free(); } Ngon::Ngon(const CPolygon &ply) { points=nullptr; segments=nullptr; count=0; segcount=0; if (ply.c==ply.d) { if (!Alloc(3,1)) return; points[0]=ply.a; points[1]=ply.b; points[2]=ply.c; segments[0]=3; } else { if (!Alloc(4,1)) return; points[0]=ply.a; points[1]=ply.b; points[2]=ply.c; points[3]=ply.d; segments[0]=4; } } Ngon::Ngon(const Ngon &src) { points=nullptr; segments=nullptr; count=0; segcount=0; CopyFrom(&src); } Ngon &Ngon::operator=(const Ngon &src) { CopyFrom(&src); return *this; } Bool Ngon::Alloc(Int32 cnt, Int32 scnt) { Free(); if (cnt) { points = NewMemClear( Int32, cnt ); if (!points) return false; if (scnt) { segments = NewMemClear( Int32, scnt ); if (!segments) { DeleteMem( points ); return false; } } count=cnt; segcount=scnt; return true; } return false; } void Ngon::Free() { DeleteMem( points ); DeleteMem( segments ); count=0; segcount=0; } Bool Ngon::CopyFrom(const Ngon *src) { Free(); if (src && src->points && src->count) { points = NewMem( Int32, src->count ); if (!points) return false; if (src->segments && src->segcount) { segments = NewMem( Int32, src->segcount ); if (!segments) { Free(); return false; } } segcount=src->segcount; count=src->count; CopyMemType(src->points, points, count ); if (segments) CopyMemType(src->segments, segments, segcount ); } return true; } Bool Ngon::CopyFrom(Int32 cnt, Int32 scnt, Int32* pts, Int32* segs) { Free(); if (pts && cnt) { points = NewMem( Int32, cnt ); if (!points) return false; if (segs && scnt) { segments = NewMem( Int32, scnt ); if (!segments) { Free(); return false; } segcount=scnt; } else { segcount = 1; segments = NewMem( Int32, segcount ); if (!segments) { Free(); return false; } } count=cnt; CopyMemType(pts, points, count ); if (segs) CopyMemType(segs, segments, segcount ); else segments[0] = cnt; } return true; } void Ngon::Release() { points=nullptr; segments=nullptr; count=0; segcount=0; } static Float CalcDet(const Vector &v1, const Vector &v2, const Vector &v3) { return v1.x * (v2.y - v3.y) + v2.x * (v3.y - v1.y) + v3.x * (v1.y - v2.y); } Float Ngon::CalcArea(Int32 seg, const Vector* p, Matrix& m) { Float a = 0.0f; Int32 l, o = 0; Vector v1(DC), v2(DC), v3(DC); if (segments[seg] < 3) return 0.0f; if (seg == 0) { // the matrix m is used to project the ngon onto a plane Vector n, prev(DC); v1 = p[points[0]]; prev = p[points[1]] - v1; for (l = 2; l < segments[0]; l++) { v2 = p[points[l]] - v1; n += Cross(prev, v2); prev = v2; } m.off = Vector64(0.0); m.v3 = !n; if (Abs(n.x) > Abs(n.y) && Abs(n.x) > Abs(n.z)) { m.v1 = Cross(Vector(0.0f, 1.0f, 0.0f), m.v3); // x axis m.v2 = Cross(m.v3, m.v1); // y axis } else if (Abs(n.y) > Abs(n.z)) { m.v1 = Cross(m.v3, Vector(0.0f, 0.0f, 1.0f)); m.v2 = Cross(m.v3, m.v1); } else { m.v2 = Cross(m.v3, Vector(1.0f, 0.0f, 0.0f)); m.v1 = Cross(m.v2, m.v3); } m = ~m; } for (l = 0; l < seg; l++) o += segments[l]; v1 = m * p[points[o]]; v2 = m * p[points[o + 1]]; for (l = 0; l < segments[seg]; l++) { v3 = m * p[points[o + (l + 2) % segments[seg]]]; a += CalcDet(v1, v2, v3); v1 = v2; v2 = v3; } return a; } ////////////////////////////////////////////////////////////////////////// NgonBaseLib *lib_ngonbase = nullptr; static NgonBaseLib *CheckNgonBaseLib(Int32 offset) { return (NgonBaseLib*)CheckLib(LIBRARY_NGON,offset,(C4DLibrary**)&lib_ngonbase); } #define NgonBaseLibCall(b) NgonBaseLib *lib = CheckNgonBaseLib(LIBOFFSET(NgonBaseLib, b)); \ if (!lib || !lib->b) return; \ (((iNgonBase*)this)->*lib->b) #define NgonBaseLibCallR(a,b) NgonBaseLib *lib = CheckNgonBaseLib(LIBOFFSET(NgonBaseLib, b)); \ if (!lib || !lib->b) return a; \ return (((iNgonBase*)this)->*lib->b) NgonBase* NgonBase::Alloc() { NgonBaseLib *lib = CheckNgonBaseLib(LIBOFFSET(NgonBaseLib,Alloc)); if (!lib) return nullptr; return (NgonBase*)lib->Alloc(); } void NgonBase::Free(NgonBase *&p) { if (!p) return; NgonBaseLib *lib = CheckNgonBaseLib(LIBOFFSET(NgonBaseLib,Free)); if (!lib) return; iNgonBase* i = (iNgonBase*)p; lib->Free(i); p = nullptr; } Bool NgonBase::CopyTo(NgonBase *dst) { NgonBaseLibCallR(false,CopyTo)((iNgonBase*)dst); } Bool NgonBase::Write(HyperFile *hf) { NgonBaseLibCallR(false,Write)(hf); } Bool NgonBase::Read(HyperFile *hf, Int32 id, Int32 level) { NgonBaseLibCallR(false,Read)(hf,id,level); } Bool NgonBase::Translate(VariableChanged *vc) { NgonBaseLibCallR(false,Translate)(vc); } Bool NgonBase::Changed(PolygonObject *op) { NgonBaseLibCallR(false,Changed)(op); } UChar NgonBase::GetEdgeStates(Int32 id) const { NgonBaseLibCallR(false,GetEdgeStates)(id); } Int32 NgonBase::GetCount() const { NgonBaseLibCallR(0,GetCount)(); } Pgon *NgonBase::GetNgons() { NgonBaseLibCallR(nullptr,GetNgons)(); } Bool NgonBase::Resize(Int32 cnt) { NgonBaseLibCallR(false,Resize)(cnt); } Int32 NgonBase::FindPolygon(Int32 id, Int32 l) const { NgonBaseLibCallR(NOTOK,FindPolygon)(id,l); } Bool NgonBase::CompactPgons() { NgonBaseLibCallR(false,CompactPgons)(); } void NgonBase::CheckPoints(PolygonObject *op) { NgonBaseLibCall(CheckPoints)(op); } void NgonBase::UpdateNgons(PolygonObject *op) { NgonBaseLibCall(UpdateNgons)(op); } Bool NgonBase::ResetPoints(PolygonObject *op) { NgonBaseLibCallR(false,ResetPoints)(op); } void NgonBase::SetFlags(Int32 flgs) { NgonBaseLibCall(SetFlags)(flgs); } Int32 NgonBase::GetFlags() const { NgonBaseLibCallR(false,GetFlags)(); } Int32 NgonBase::GetDirtyCount() const { NgonBaseLibCallR(false,GetDirtyCount)(); } void NgonBase::Dirty() { NgonBaseLibCall(Dirty)(); } void NgonBase::InitMap() { NgonBaseLibCall(InitMap)(); } void NgonBase::FreeMap() { NgonBaseLibCall(FreeMap)(); } Bool NgonBase::Remove(Int32 id, Bool force) { NgonBaseLibCallR(false,Remove)(id,force); } Bool NgonBase::ToSelect(BaseSelect *pSelect, Int32 mode) { NgonBaseLibCallR(false,ToSelect)(pSelect,mode); } void NgonBase::GetCenter(Int32 id, const CPolygon *vadr, const Vector *padr, Vector *ip, Vector *in) { NgonBaseLibCall(GetCenter)(id,vadr,padr,ip,in); } Bool NgonBase::RemapEdge(Int32 oedge, Int32 *nedges, Int32 ncnt) { NgonBaseLibCallR(false,RemapEdge)(oedge,nedges,ncnt); } Bool NgonBase::Create(UInt32 *nedges, Int32 ncnt) { NgonBaseLibCallR(false,Create)(nedges,ncnt); } Bool NgonBase::RemapPolygon(Int32 oply, Int32 nply) { NgonBaseLibCallR(false,RemapPolygon)(oply,nply); } Bool NgonBase::Copy(Pgon *src, Pgon *dst) { NgonBaseLibCallR(false,Copy)(src,dst); } Bool NgonBase::Validate(PolygonObject *op) { NgonBaseLibCallR(false,Validate)(op); } Bool NgonBase::IsValidNgon(Pgon *pgon, const CPolygon *vadr) { NgonBaseLibCallR(false,IsValidNgon)(pgon,vadr); } Int32 NgonBase::BuildNgon(Int32 *inner, Int32 *outer, Int32 icnt, Int32 ocnt, const CPolygon *vadr, const Vector *padr) { NgonBaseLibCallR(NOTOK,BuildNgon)(inner,outer,icnt,ocnt,vadr,padr); } Int32 NgonBase::BuildNgonFromPolys(Int32 *polys, Int32 *outer, Int32 pcnt, Int32 ocnt, const CPolygon *vadr, const Vector *padr) { NgonBaseLibCallR(NOTOK,BuildNgonFromPolys)(polys,outer,pcnt,ocnt,vadr,padr); } Bool NgonBase::Verify(const CPolygon *vadr, Int32 vcnt, UInt32 flags, Pgon *pgon) { NgonBaseLibCallR(false,Verify)(vadr,vcnt,flags,pgon); } Pgon *NgonBase::AllocNgon(Int32 edge_cnt) { NgonBaseLibCallR(nullptr,AllocNgon)(edge_cnt); } void NgonBase::FreeNgon(Pgon *&pgon) { NgonBaseLibCall(FreeNgon)(pgon); } Bool NgonBase::SetNgon(Int32 index, Pgon *src) { NgonBaseLibCallR(false,SetNgon)(index,src); } Bool NgonBase::SetNgon(Int32 index, UInt32 *edges, Int32 edge_cnt) { NgonBaseLibCallR(false,SetNgonE)(index,edges,edge_cnt); } ////////////////////////////////////////////////////////////////////////// Vector Pgon::CalcNormal(const Vector* padr, const CPolygon* polys) const { Vector v; Int32 i; for (i = 0; i < m_Count; i++) { if (!m_Edge[i].IsFirst()) continue; const CPolygon &p = polys[m_Edge[i].ID()]; if (p.c==p.d) v += Cross((padr[p.b]-padr[p.a]),(padr[p.c]-padr[p.a])); else v += Cross((padr[p.b]-padr[p.d]),(padr[p.c]-padr[p.a])); } return !v; } void Pgon::GetMpRad(const Vector* padr, const CPolygon* polys, Vector &mp, Vector &rad) const { MinMax mm; Int32 i; for (i = 0; i < m_Count; i++) { if (!m_Edge[i].IsFirst()) continue; const CPolygon &p = polys[m_Edge[i].ID()]; mm.AddPoint(padr[p.a]); mm.AddPoint(padr[p.b]); mm.AddPoint(padr[p.c]); if (p.c != p.d) mm.AddPoint(padr[p.d]); } mm.GetMpRad(&mp, &rad); } Int32 Pgon::GetSegmentCount() const { Int32 s=0,e; if (m_Count<1 || !m_Edge) return 0; for (e=0;e