// Domain.cpp : implementation file // #include "stdafx.h" //#include "OTSData.h" #include "Domain.h" #include "XMLSerialization.h" namespace OTSDATA { using namespace xmls; // CDomain // constructor CDomain::CDomain() { // initialization Init(); } CDomain::CDomain(DOMAIN_SHAPE a_nShape, CRect a_rectDomain) { // initialization Init(); // assign class members m_nShape = a_nShape; m_rectDomain = a_rectDomain; } // copy constructor CDomain::CDomain(const CDomain& a_oSource) { // can't copy itself if (&a_oSource == this) { return; } // copy data over Duplicate(a_oSource); } // copy constructor CDomain::CDomain(CDomain* a_poSource) { // input check ASSERT(a_poSource); if (!a_poSource) { return; } // can't copy itself if (a_poSource == this) { return; } // copy data over Duplicate(*a_poSource); } // =operator CDomain& CDomain::operator=(const CDomain& a_oSource) { // cleanup Cleanup(); // copy the class data over Duplicate(a_oSource); // return class return *this; } // ==operator BOOL CDomain::operator==(const CDomain& a_oSource) { return m_nShape == a_oSource.m_nShape && m_rectDomain == a_oSource.m_rectDomain; } // destructor CDomain::~CDomain() { // cleanup Cleanup(); } // CDomain functions // public // check if the region is valid BOOL CDomain::IsInvalid() const { return (m_nShape < DOMAIN_SHAPE::MIN) || m_nShape > DOMAIN_SHAPE::MAX || m_rectDomain.IsRectEmpty(); } void CDomain::SetPolygonPoint(const std::vector a_PolygonPoint) { std::vector ps = a_PolygonPoint; m_PolygonPoint.clear(); for (auto p : ps) { m_PolygonPoint.push_back(p); } } // check if have common area with the given domain BOOL CDomain::IntersectDomain(const CDomain& a_oDomain) { // return FALSE if any domain of the two is invalid if (IsInvalid() || a_oDomain.IsInvalid()) { return FALSE; } // create two CRgn objects with the two region objects CRect rectCur, rectGiven; rectCur = GetDomainRect(); rectGiven = a_oDomain.GetDomainRect(); CRgn rgnCur, rgnGiven, rgnTest; BOOL bRgnCur, bRgnGiven; bRgnCur = rgnTest.CreateEllipticRgnIndirect(rectCur); if (IsRound()) { bRgnCur = rgnCur.CreateEllipticRgnIndirect(rectCur); } else { bRgnCur = rgnCur.CreateRectRgnIndirect(rectCur); } if (a_oDomain.IsRound()) { bRgnGiven = rgnGiven.CreateEllipticRgnIndirect(rectGiven); } else { rgnGiven.CreateRectRgnIndirect(rectGiven); } // combine the two CRgn objects with RGN_AND int nCombineResult = rgnTest.CombineRgn(&rgnCur, &rgnGiven, RGN_AND); // return TRUE if combine success and combine result is not empty return (nCombineResult != ERROR) && (nCombineResult != NULLREGION); } // check if the point is in domain BOOL CDomain::PtInDomain(const CPoint& a_poiCheck) const { // return FALSE if is invalid if (IsInvalid()) { return FALSE; } // check sharp if (IsRound()) { // round double dRoundRegionRadius = (double)GetDomainRect().Width() / 2000.0; dRoundRegionRadius = dRoundRegionRadius * dRoundRegionRadius; double dDisToRegioCenter; double dX, dY; dX = (double)abs(GetDomainCenter().x - a_poiCheck.x) / 1000; dY = (double)abs(GetDomainCenter().y - a_poiCheck.y) / 1000; dX = dX * dX; dY = dY * dY; dDisToRegioCenter = dX + dY; if (dRoundRegionRadius >= dDisToRegioCenter) { // in region return TRUE; } else { // not in region return FALSE; } } else { // rectangle // use CRect method return GetDomainRect().PtInRect(a_poiCheck); } } // check if the given domain is in domain BOOL CDomain::DomainInDomain(const CDomain& a_oDomain) { // return FALSE if any domain of the two is invalid if (IsInvalid() || a_oDomain.IsInvalid()) { return FALSE; } // create two CRgn objects with the two domain objects CRect rectCur, rectGiven; rectCur = GetDomainRect(); rectGiven = a_oDomain.GetDomainRect(); CRgn rgnCur, rgnGiven, rgnTest; BOOL bRgnCur, bRgnGiven; bRgnCur = rgnTest.CreateEllipticRgnIndirect(rectCur); if (IsRound()) { bRgnCur = rgnCur.CreateEllipticRgnIndirect(rectCur); } else { bRgnCur = rgnCur.CreateRectRgnIndirect(rectCur); } if (a_oDomain.IsRound()) { bRgnGiven = rgnGiven.CreateEllipticRgnIndirect(rectGiven); } else { bRgnGiven = rgnGiven.CreateRectRgnIndirect(rectGiven); } // combine the two CRgn objects with RGN_AND int nCombineResult = rgnTest.CombineRgn(&rgnCur, &rgnGiven, RGN_AND); // return FALSE if combine failed or combine result is empty if (nCombineResult == ERROR || nCombineResult == NULLREGION) { return FALSE; } // the combined region equals the test domain means that the test domain is in the domain, return TRUE return rgnTest.EqualRgn(&rgnGiven); } // cleanup void CDomain::Cleanup() { // need to do nothing at the moment m_PolygonPoint.clear(); } // initialization void CDomain::Init() { m_nShape = DOMAIN_SHAPE::INVALID; m_rectDomain = CRect(0, 0, 0, 0); m_PolygonPoint.clear(); } // duplication void CDomain::Duplicate(const CDomain& a_oSource) { // initialization Init(); // copy data over m_nShape = a_oSource.m_nShape; m_rectDomain = a_oSource.m_rectDomain; m_PolygonPoint = a_oSource.m_PolygonPoint; } void CDomain::Serialize(bool isStoring, tinyxml2::XMLDocument* classDoc, tinyxml2::XMLElement* rootNode) { xmls::Slo slo; xmls::xInt xnShape; xmls::xRect xRecDomain; xmls::xString xPolygonPoint; //register at this time point can ensure that the objects aren't nullptr especialy the smart pointer object. //Slo::Clear(); slo.Register("shape", &xnShape); slo.Register("rectDomian", &xRecDomain); slo.Register("PolygonPoint", &xPolygonPoint); if (isStoring) { xnShape = (int)m_nShape; if (m_nShape == DOMAIN_SHAPE::POLYGON) { CString polygonPoints = _T(""); if (m_PolygonPoint.size() > 0) { for (size_t i = 0; i < m_PolygonPoint.size(); i++) { CString X = _T(""); X.Format(_T("%ld"), m_PolygonPoint[i].x); CString Y = _T(""); Y.Format(_T("%ld"), m_PolygonPoint[i].y); //polygonPoints.Format(_T("%ld"), m_PolygonPoint[i].y); polygonPoints.Append(X); polygonPoints.Append(","); polygonPoints.Append(Y); polygonPoints.Append("_"); } } xPolygonPoint = polygonPoints; } //we have to save the rectangle parameter according to the previouse rule.(left,top,width,height or centerX centerY,diamiter,0) xRecDomain = xRect(m_rectDomain, (int)m_nShape); slo.Serialize(true, classDoc, rootNode); } else { slo.Serialize(false, classDoc, rootNode); m_nShape = (DOMAIN_SHAPE)xnShape.value(); m_rectDomain = xRecDomain.value(); if (m_nShape == DOMAIN_SHAPE::POLYGON) { std::vector point; SplitString(xPolygonPoint.value(), point, "_"); for (int i = 0; i < point.size(); i++) { std::vector pointTemp; SplitString(point[i], pointTemp, ","); /*m_PolygonPoint[i].x = stoll(pointTemp[0], 0, 0); m_PolygonPoint[i].y = stoll(pointTemp[1], 0, 0);*/ long x = atoi(pointTemp[0].c_str()); long y = atoi(pointTemp[1].c_str()); m_PolygonPoint.push_back(CPoint(x, y)); } } //do the regulation int nCentreX = m_rectDomain.left; int nCentreY = m_rectDomain.top; int nWidth; int nHeight; int nDiameter; if (m_nShape == DOMAIN_SHAPE::ROUND) { nDiameter = m_rectDomain.right; // create domain m_rectDomain.left = 0; m_rectDomain.top = 0; m_rectDomain.right = nDiameter; m_rectDomain.bottom = nDiameter; this->OffsetDomain(CPoint(nCentreX - (nDiameter / 2), nCentreY - (nDiameter / 2))); } else if (m_nShape == DOMAIN_SHAPE::RECTANGLE) { nWidth = m_rectDomain.right; nHeight = m_rectDomain.bottom; m_rectDomain.left = 0; m_rectDomain.top = 0; m_rectDomain.right = nWidth; m_rectDomain.bottom = nHeight; this->OffsetDomain(CPoint(nCentreX - (nWidth / 2), nCentreY - (nHeight / 2))); } } } }