#include "StdAfx.h" #include "_cgal.h" #include "mg_cgal_export.h" /* modernGlue.dll 完全满足ABI安全,但要安全使用, 请保证: modernGlue.dll 申请的内存,一定要用 modernGlue.dll 内的函数释放 本工程申请的内存,一定在本工程内释放. 不要跨dll释放内存. */ // 检测 pod 类型 #define CGAL_STATIC_ASSERT(expr, msg) typedef char ERROR_##msg[ (expr) ? 1 : -1 ] namespace { void pt_copy(const AcGePoint2d &src, _cgal::Pt2d &pt) { pt.x = src.x; pt.y = src.y; } void pt_copy(const _cgal::Pt2d &src, AcGePoint2d &pt) { pt.x = src.x; pt.y = src.y; } void pt_copy(const AcGePoint3d &src, _cgal::Pt3d &pt) { pt.x = src.x; pt.y = src.y; pt.z = src.z; } void pt_copy(const _cgal::Pt3d &src, AcGePoint3d &pt) { pt.x = src.x; pt.y = src.y; pt.z = src.z; } void pt_copy(const AcGePoint3d &src, _cgal::Pt2d &pt) { pt.x = src.x; pt.y = src.y; } void pt_copy(const _cgal::Pt2d &src, AcGePoint3d &pt) { pt.x = src.x; pt.y = src.y; pt.z = .0; } template void vector_arr(const std::vector &src, _cgal::CgalArray &dest) { if (src.empty()) return; dest.count = (int)src.size(); dest.pData = new T_DST[dest.count](); for (int i(0); i < dest.count; ++i) pt_copy(src[i], dest.pData[i]); } template void arr_vector(const _cgal::CgalArray &src, std::vector &dest) { if (src.count <= 0) return; dest.resize(src.count); for (int i(0); i < src.count; ++i) pt_copy(src.pData[i], dest[i]); } void pwh_gePwh(const _cgal::Pwh2d &src, Geometry::GePwh2d &dst) { arr_vector(src.outer_boundary.vertices, dst.outer_boundary.vertexs); dst.inner_holes.resize(src.inner_holes.count); for (int i(0); i < src.inner_holes.count; ++i) arr_vector(src.inner_holes.pData[i].vertices, dst.inner_holes[i].vertexs); } void pwh_gePwh(const _cgal::Pwh2dList &src, Geometry::GePwh2dList &dst) { dst.resize(src.count); for (int i(0); i < src.count; ++i) pwh_gePwh(src.pData[i], dst[i]); } ///////////////////////////////////////////////////////////////////////////////////// template class auto_release { CGAL_STATIC_ASSERT(__is_pod(T), Only_POD_types_allowed); public: typedef void (*deleter)(T&); private: T m_T; deleter m_deleter; // 保存 C 接口的释放函数指针 // 封死拷贝语义 auto_release(const auto_release &); auto_release &operator=(const auto_release &); public: auto_release(const T &t, const deleter &delfunc) : m_T(t), m_deleter(delfunc) {} auto_release(): m_deleter(NULL) { ::memset(&m_T, 0, sizeof(T)); } ~auto_release() { if (m_deleter) m_deleter(m_T); } const T& get() const { return m_T; } T& get() { return m_T; } void set(T &t, const deleter &delfunc) { if (m_deleter) m_deleter(m_T); m_T = t; m_deleter = delfunc; } }; template void cgal_free_array(_cgal::CgalArray &Arr) { if (Arr.pData) { delete[] Arr.pData; // 在 dll 的堆里安全释放 Arr.pData = 0; Arr.count = 0; } } template void cgal_free_polygon(T &polygon) { cgal_free_array(polygon.vertices); } template void cgal_free_polygonList(T &lst) { for (int i(0); i < lst.count; ++i) cgal_free_polygon(lst.pData[i]); cgal_free_array(lst); } void cgal_free_pwh2d(_cgal::Pwh2d &pwh) { cgal_free_polygon(pwh.outer_boundary); cgal_free_polygonList(pwh.inner_holes); } void cgal_free_pwh2dList(_cgal::Pwh2dList &pwhlst) { for (int i(0); i < pwhlst.count; ++i) cgal_free_pwh2d(pwhlst.pData[i]); cgal_free_array(pwhlst); } void free_local_obj(_cgal::Pt2dArr &ar) { cgal_free_array(ar); } void free_local_obj(_cgal::Pt3dArr &ar) { cgal_free_array(ar); } void free_local_obj(_cgal::IntArray &ar) { cgal_free_array(ar); } void free_local_obj(_cgal::Pwh2d &ar) { cgal_free_pwh2d(ar); } void free_local_obj(_cgal::Pwh2dList &ar) { cgal_free_pwh2dList(ar); } void free_local_obj(_cgal::Polygon2d &ar) { cgal_free_polygon(ar); } void free_local_obj(_cgal::Polygon2dList &ar) { cgal_free_polygonList(ar); } void free_local_obj(_cgal::Polygon3d &ar) { cgal_free_polygon(ar); } void free_local_obj(_cgal::Polygon3dList &ar) { cgal_free_polygonList(ar); } void free_mg_obj(_cgal::Pt2dArr &ar) { mg_cgal_free_Pt2dArray(ar); } void free_mg_obj(_cgal::Pt3dArr &ar) { mg_cgal_free_Pt3dArray(ar); } void free_mg_obj(_cgal::IntArray &ar) { mg_cgal_free_IntArray(ar); } void free_mg_obj(_cgal::Pwh2d &ar) { mg_cgal_free_Pwh2d(ar); } void free_mg_obj(_cgal::Pwh2dList &ar) { mg_cgal_free_Pwh2dList(ar); } void free_mg_obj(_cgal::Polygon2d &ar) { mg_cgal_free_Polygon2d(ar); } void free_mg_obj(_cgal::Polygon2dList &ar) { mg_cgal_free_Polygon2dList(ar); } void free_mg_obj(_cgal::Polygon3d &ar) { mg_cgal_free_Polygon3d(ar); } void free_mg_obj(_cgal::Polygon3dList &ar) { mg_cgal_free_Polygon3dList(ar); } template _cgal::CgalArray get_cgal_ptArr(const std::vector &arPts) { typedef _cgal::CgalArray _ARR; _ARR out; ::memset(&out, 0, sizeof(_ARR)); // 一定要清空一下,保证 arpts 为空时,out也是空 vector_arr(arPts, out); return out; } template void get_cgal_ptArr(const std::vector &arPts, auto_release<_cgal::CgalArray> &auto_rel) { _cgal::CgalArray out = get_cgal_ptArr(arPts); auto_rel.set(out, free_local_obj); } template T_DST get_cgal_empty_obj() { T_DST dst; ::memset(&dst, 0, sizeof(T_DST)); return dst; } template void get_cgal_empty_obj(auto_release &auto_rel) { T_DST dst = get_cgal_empty_obj(); auto_rel.set(dst, free_mg_obj); } // T_SRC : Geometry::GePolygonXd // T_DST : _cgal::PolygonXd template T_DST get_cgal_polygon(const T_SRC &holds) { T_DST out; ::memset(&out, 0, sizeof(T_DST)); vector_arr(holds.vertexs, out.vertices); return out; } template void get_cgal_polygon(const T_SRC &holds, auto_release &auto_rel) { T_DST out = get_cgal_polygon(holds); auto_rel.set(out, free_local_obj); } // T_SRC : AcGePoint3d (GePolyArray3d) // T_DST : _cgal::PolygonXdList template _cgal::CgalArray get_cgal_polygonArr(const std::vector> &holds) { _cgal::CgalArray out; out.count = (int)holds.size(); out.pData = NULL; if (out.count > 0) { out.pData = new T_DST[out.count](); for (int i(0); i < out.count; ++i) vector_arr(holds[i], out.pData[i].vertices); } return out; } // T_SRC : AcGePoint3d (GePolyArray3d) // T_DST : _cgal::PolygonXdList template void get_cgal_polygonArr(const std::vector> &holds, auto_release<_cgal::CgalArray> &auto_rel) { _cgal::CgalArray out = get_cgal_polygonArr(holds); auto_rel.set(out, free_local_obj); } template _cgal::CgalArray get_cgal_polygonList(const std::vector &src) { _cgal::CgalArray out; out.count = (int)src.size(); out.pData = NULL; if (out.count > 0) { out.pData = new T_DST[out.count](); for (int i(0); i < out.count; ++i) out.pData[i] = get_cgal_polygon(src[i]); } return out; } void get_cgal_pwh2d(const Geometry::GePwh2d &src, auto_release<_cgal::Pwh2d> &auto_rel) { _cgal::Pwh2d pwh; pwh.outer_boundary = get_cgal_polygon(src.outer_boundary); pwh.inner_holes = get_cgal_polygonList(src.inner_holes); auto_rel.set(pwh, free_local_obj); } } namespace Geometry { void delaunayTriangulationMesh(const GePoint3dArray &arPts , AcGePoint3dArray &vertexArray , AcArray &faceArray) { GePolyArray3d holds; delaunayTriangulationMeshWithHolds(arPts, holds, vertexArray, faceArray); } void delaunayTriangulationMeshWithHolds(const GePoint3dArray &arPts , const GePolyArray3d &holds , AcGePoint3dArray &vertexArray , AcArray &faceArray) { auto_release<_cgal::Pt3dArr> _arpts; get_cgal_ptArr(arPts, _arpts); auto_release<_cgal::Polygon3dList> _holds; get_cgal_polygonArr(holds, _holds); auto_release<_cgal::Pt3dArr> _vecties; get_cgal_empty_obj(_vecties); auto_release<_cgal::IntArray> _faces; get_cgal_empty_obj(_faces); mg_cgal_delaunayTriangulationMeshWithHolds(_arpts.get(), _holds.get(), _vecties.get(), _faces.get()); AcGePoint3d pt3d; for (int i(0); i < _vecties.get().count; ++i) { pt_copy(_vecties.get().pData[i], pt3d); vertexArray.append(pt3d); } faceArray.setLogicalLength(_faces.get().count); ::memcpy(faceArray.asArrayPtr(), _faces.get().pData, _faces.get().count * sizeof(int)); } void calcConvexHull2D(const GePoint2dArray & arPts, GePoint2dArray & poly) { auto_release<_cgal::Pt2dArr> _arPts, _poly; get_cgal_ptArr(arPts, _arPts); get_cgal_empty_obj(_poly); mg_cgal_calcConvexHull2D_2d_2d(_arPts.get(), _poly.get()); arr_vector(_poly.get(), poly); } void calcConvexHull2D(const GePoint3dArray &arPts, GePoint2dArray &poly) { auto_release<_cgal::Pt3dArr> _arPts; get_cgal_ptArr(arPts, _arPts); auto_release<_cgal::Pt2dArr> _poly; get_cgal_empty_obj(_poly); mg_cgal_calcConvexHull2D_3d_2d(_arPts.get(), _poly.get()); arr_vector(_poly.get(), poly); } void calcConvexHull2D(const GePoint3dArray &arPts, GePoint3dArray &poly) { auto_release<_cgal::Pt3dArr> _arPts; get_cgal_ptArr(arPts, _arPts); auto_release<_cgal::Pt3dArr> _poly; get_cgal_empty_obj(_poly); mg_cgal_calcConvexHull2D_3d_3d(_arPts.get(), _poly.get()); arr_vector(_poly.get(), poly); } bool is_vaild_polygon(const GePwh2d &geP) { auto_release<_cgal::Pwh2d> _geP; get_cgal_pwh2d(geP, _geP); return mg_cgal_is_vaild_polygon_with_hole(_geP.get()); } bool is_vaild_polygon(const GePolygon2d & geP) { auto_release<_cgal::Polygon2d> _geP; get_cgal_polygon(geP, _geP); return mg_cgal_is_vaild_polygon(_geP.get()); } bool is_intersect(const GePwh2d &geP, const GePwh2d &geQ) { auto_release<_cgal::Pwh2d> _geP, _geQ; get_cgal_pwh2d(geP, _geP); get_cgal_pwh2d(geQ, _geQ); return mg_cgal_is_intersect(_geP.get(), _geQ.get()); } void intersect(const GePwh2d &geP , const GePwh2d &geQ , GePwh2dList &gepwhlst) { auto_release<_cgal::Pwh2d> _geP, _geQ; get_cgal_pwh2d(geP, _geP); get_cgal_pwh2d(geQ, _geQ); auto_release<_cgal::Pwh2dList> _gepwhlst; get_cgal_empty_obj<_cgal::Pwh2dList>(_gepwhlst); mg_cgal_intersect(_geP.get(), _geQ.get(), _gepwhlst.get()); pwh_gePwh(_gepwhlst.get(), gepwhlst); } bool join( const GePwh2d &geP , const GePwh2d &geQ , GePwh2d &gepwh) { auto_release<_cgal::Pwh2d> _geP, _geQ; get_cgal_pwh2d(geP, _geP); get_cgal_pwh2d(geQ, _geQ); auto_release<_cgal::Pwh2d> _gepwh; get_cgal_empty_obj<_cgal::Pwh2d>(_gepwh); bool brel = mg_cgal_join(_geP.get(), _geQ.get(), _gepwh.get()); pwh_gePwh(_gepwh.get(), gepwh); return brel; } void difference( const GePwh2d &geP , const GePwh2d &geQ , GePwh2dList &gepwhlst) { auto_release<_cgal::Pwh2d> _geP, _geQ; get_cgal_pwh2d(geP, _geP); get_cgal_pwh2d(geQ, _geQ); auto_release<_cgal::Pwh2dList> _gepwhlst; get_cgal_empty_obj<_cgal::Pwh2dList>(_gepwhlst); mg_cgal_difference(_geP.get(), _geQ.get(), _gepwhlst.get()); pwh_gePwh(_gepwhlst.get(), gepwhlst); } void symmetric_difference( const GePwh2d &geP , const GePwh2d &geQ , GePwh2dList &gepwhlst) { auto_release<_cgal::Pwh2d> _geP, _geQ; get_cgal_pwh2d(geP, _geP); get_cgal_pwh2d(geQ, _geQ); auto_release<_cgal::Pwh2dList> _gepwhlst; get_cgal_empty_obj<_cgal::Pwh2dList>(_gepwhlst); mg_cgal_symmetric_difference(_geP.get(), _geQ.get(), _gepwhlst.get()); pwh_gePwh(_gepwhlst.get(), gepwhlst); } Geometry::Bounded_side boundary_check(const AcGePoint2d & pt, const GePwh2d & gepwh) { _cgal::Pt2d _pt; pt_copy(pt, _pt); auto_release<_cgal::Pwh2d> _gepwh; get_cgal_pwh2d(gepwh, _gepwh); return (Geometry::Bounded_side)mg_cgal_boundary_check(_pt, _gepwh.get()); } bool is_counterclockwise(const GePwh2d & P) { auto_release<_cgal::Pwh2d> _P; get_cgal_pwh2d(P, _P); return mg_cgal_is_counterclockwise_with_hole(_P.get()); } bool is_counterclockwise(const AcGePoint2d &ptS , const AcGePoint2d &ptM , const AcGePoint2d &ptE ) { _cgal::Pt2d _ptS, _ptM, _ptE; pt_copy(ptS, _ptS); pt_copy(ptM, _ptM); pt_copy(ptE, _ptE); return mg_cgal_is_counterclockwise(_ptS, _ptM, _ptE); } void convexHull2d(const AcGePoint2dArray &input, AcGePoint2dArray &output) { GePoint2dArray arIn(input.length()); ::memcpy(&(*arIn.begin()), input.asArrayPtr(), input.length() * sizeof(AcGePoint2d)); auto_release<_cgal::Pt2dArr> _input, _out; get_cgal_ptArr(arIn, _input); get_cgal_empty_obj(_out); mg_cgal_convexHull2d(_input.get(), _out.get()); output.setLogicalLength(_out.get().count); ::memcpy(output.asArrayPtr(), _out.get().pData, _out.get().count * sizeof(AcGePoint2d)); } }