///////////////////////////////////////////////////////////////////////////// // Copyright: (C) 2008-19 Cesar Mauri Loba - CREA Software Systems // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . ///////////////////////////////////////////////////////////////////////////// #include "visiblenormroi.h" #include #define SELECTION_TOLERANCE 3 CVisibleNormROI::CVisibleNormROI(void) : CNormROI() { m_cursorOver= OVER_NONE; m_showOrientation= false; m_degradation= 0; } CVisibleNormROI::CVisibleNormROI(float width, float height, float x, float y) : CNormROI (width, height, x, y) { m_cursorOver= OVER_NONE; m_showOrientation= false; m_degradation= 0; } CVisibleNormROI::~CVisibleNormROI(void) { } // // Locking support. Locks on parent // inline void CVisibleNormROI::Lock() { if (m_pParentROI) ((CVisibleNormROI *) m_pParentROI)->Lock(); else m_CriticalSection.Enter(); } inline void CVisibleNormROI::Unlock() { if (m_pParentROI) ((CVisibleNormROI *) m_pParentROI)->Unlock(); else m_CriticalSection.Leave(); } void CVisibleNormROI::SetP1Resize (const float x, const float y) { Lock(); CNormROI::SetP1Resize (x, y); Unlock(); } void CVisibleNormROI::SetP1Move (const float x, const float y) { Lock(); CNormROI::SetP1Move (x, y); Unlock(); } void CVisibleNormROI::SetP2Resize (const float x, const float y) { Lock(); CNormROI::SetP2Resize (x, y); Unlock(); } void CVisibleNormROI::SetCenter (const float x, const float y) { Lock(); CNormROI::SetCenter (x, y); Unlock(); } void CVisibleNormROI::GetCenter (float& x, float& y) { Lock(); CNormROI::GetCenter (x, y); Unlock(); } void CVisibleNormROI::SetSize (const float width, const float height) { Lock(); CNormROI::SetSize (width, height); Unlock(); } void CVisibleNormROI::GetSize (float& width, float& height) { Lock(); CNormROI::GetSize (width, height); Unlock(); } // Overriden IPL methods to support locking void CVisibleNormROI::SetP1ResizeImg (const CIplImage *pImg, const int x, const int y) { Lock(); CNormROI::SetP1ResizeImg (pImg, x, y); Unlock(); } void CVisibleNormROI::SetP1MoveImg (const CIplImage *pImg, const int x, const int y) { Lock(); CNormROI::SetP1MoveImg (pImg, x, y); Unlock(); } void CVisibleNormROI::SetP2ResizeImg (const CIplImage *pImg, const int x, const int y) { Lock(); CNormROI::SetP2ResizeImg (pImg, x, y); Unlock(); } void CVisibleNormROI::SetCenterImg (const CIplImage *pImg, const int x, const int y) { Lock(); CNormROI::SetCenterImg (pImg, x, y); Unlock(); } void CVisibleNormROI::GetCenterImg (const CIplImage *pImg, int& x, int& y) { Lock(); CNormROI::GetCenterImg (pImg, x, y); Unlock(); } void CVisibleNormROI::SetSizeImg (const CIplImage *pImg, const int width, const int height) { Lock(); CNormROI::SetSizeImg (pImg, width, height); Unlock(); } void CVisibleNormROI::GetBoxImg (const CIplImage *pImg, int& x, int& y, int& width, int& height) { Lock(); CNormROI::GetBoxImg (pImg, x, y, width, height); Unlock(); } void CVisibleNormROI::GetBoxImg (const CIplImage *pImg, CvRect& box) { Lock(); CNormROI::GetBoxImg (pImg, box); Unlock(); } bool CVisibleNormROI::RegisterChildROI (CVisibleNormROI* pNormROI) { // Ensures that child is really a CVisibleNormROI object // (perhaps somewhat paranoic hehe) if (!dynamic_cast(pNormROI)) { assert (false); return false; } // Lock child pNormROI->m_CriticalSection.Enter(); // Lock this Lock(); bool retval= CNormROI::RegisterChildROI (pNormROI); // Unlock child pNormROI->m_CriticalSection.Leave(); // Unlock this Unlock(); return retval; } bool CVisibleNormROI::UnregisterChildROI (CVisibleNormROI* pNormROI) { Lock(); bool retval= CNormROI::UnregisterChildROI (pNormROI); Unlock(); return retval; } // // Interaction code // void CVisibleNormROI::GetDirectionSegment (const cv::Size& winSize, CvPoint& p1, CvPoint& p2) { GetP1P2Integer (winSize, p1, p2); float line_lenght= sqrtf ( powf((float)(p2.x - p1.x), 2.0f) + powf((float)(p2.y - p1.y), 2.0f)) * 1.1f / 2.0f; float cx= (float)(p1.x + p2.x) / 2.0f; float cy= (float)(p1.y + p2.y) / 2.0f; p1.x= (int) (cx + 0.5f); p1.y= (int) (cy + 0.5f); p2.x= (int) (cx + (line_lenght) * cos (GetRotation()) + 0.5f); p2.y= (int) (cy - (line_lenght) * sin (GetRotation()) + 0.5f); } // Cursor motion, no click int CVisibleNormROI::OnMouseMovedNoClick (const cv::Size& winSize, const cv::Point& cursor) { Lock (); int retval= OnMouseMovedNoClickRec (winSize, cursor); Unlock(); return retval; } int CVisibleNormROI::OnMouseMovedNoClickRec (const cv::Size& winSize, const cv::Point& cursor) { int retval; TNormROIListIterator i; retval= OnMouseMovedNoClick0 (winSize, cursor); if (retval!= OVER_NONE) return retval; for(i= m_childROIs.begin(); i != m_childROIs.end(); ++i) { CVisibleNormROI* pChild= dynamic_cast(*i); assert (pChild); retval= pChild->OnMouseMovedNoClickRec (winSize, cursor); if (retval!= OVER_NONE) return retval; } return OVER_NONE; } int CVisibleNormROI::OnMouseMovedNoClick0 (const cv::Size& winSize, const cv::Point& cursor) { CvPoint p1, p2, or_p1, or_p2; GetDirectionSegment (winSize, or_p1, or_p2); GetP1P2Integer (winSize, p1, p2); // Motion only. Used to update mouse pointer. m_cursorOver= OVER_NONE; if (m_showOrientation && cursor.x>= or_p2.x - SELECTION_TOLERANCE && cursor.x<= or_p2.x + SELECTION_TOLERANCE && cursor.y>= or_p2.y - SELECTION_TOLERANCE && cursor.y<= or_p2.y + SELECTION_TOLERANCE) { m_cursorOver= OVER_ORIENTER; } else if (cursor.x>= p1.x - SELECTION_TOLERANCE && cursor.x<= p1.x + SELECTION_TOLERANCE && cursor.y>= p1.y - SELECTION_TOLERANCE && cursor.y<= p1.y + SELECTION_TOLERANCE) { m_cursorOver= OVER_UL_CORNER; } else if (cursor.x>= p2.x - SELECTION_TOLERANCE && cursor.x<= p2.x + SELECTION_TOLERANCE && cursor.y>= p2.y - SELECTION_TOLERANCE && cursor.y<= p2.y + SELECTION_TOLERANCE) { m_cursorOver= OVER_BR_CORNER; } else { if (cursor.y>= p1.y - SELECTION_TOLERANCE && cursor.y<= p2.y + SELECTION_TOLERANCE) { // Cursor in Y range, check is cursor over vertical lines if (cursor.x>= p1.x - SELECTION_TOLERANCE && cursor.x<= p1.x + SELECTION_TOLERANCE) m_cursorOver= OVER_LEFT_LINE; else if (cursor.x>= p2.x - SELECTION_TOLERANCE && cursor.x<= p2.x + SELECTION_TOLERANCE) m_cursorOver= OVER_RIGHT_LINE; } if (cursor.x>= p1.x - SELECTION_TOLERANCE && cursor.x<= p2.x + SELECTION_TOLERANCE) { // Cursor in X range, check is cursor over horizontal lines if (cursor.y>= p1.y - SELECTION_TOLERANCE && cursor.y<= p1.y + SELECTION_TOLERANCE) m_cursorOver= OVER_UPPER_LINE; else if (cursor.y>= p2.y - SELECTION_TOLERANCE && cursor.y<= p2.y + SELECTION_TOLERANCE) m_cursorOver= OVER_BOTTOM_LINE; } } return m_cursorOver; } // Cursor motion, left button down bool CVisibleNormROI::OnMouseMovedClick (const cv::Size& winSize, const cv::Point& cursor, const cv::Point& prevCursor) { Lock (); bool retval= OnMouseMovedClickRec (winSize, cursor, prevCursor); Unlock(); return retval; } bool CVisibleNormROI::OnMouseMovedClickRec (const cv::Size& winSize, const cv::Point& cursor, const cv::Point& prevCursor) { TNormROIListIterator i; if (OnMouseMovedClick0 (winSize, cursor, prevCursor)) return true; for(i= m_childROIs.begin(); i != m_childROIs.end(); ++i) { CVisibleNormROI* pChild= dynamic_cast(*i); assert (pChild); if (pChild->OnMouseMovedClickRec (winSize, cursor, prevCursor)) return true; } return false; } bool CVisibleNormROI::OnMouseMovedClick0 (const cv::Size& winSize, const cv::Point& cursor, const cv::Point& prevCursor) { CvPoint p1, p2, or_p1, or_p2; GetDirectionSegment (winSize, or_p1, or_p2); GetP1P2Integer (winSize, p1, p2); if (m_cursorOver> OVER_NONE) { switch (m_cursorOver) { case OVER_LEFT_LINE: p1.x+= cursor.x - prevCursor.x; SetP1ResizeInteger (winSize, p1.x, p1.y); break; case OVER_BOTTOM_LINE: p2.y+= cursor.y - prevCursor.y; SetP2ResizeInteger (winSize, p2.x, p2.y); break; case OVER_RIGHT_LINE: p2.x+= cursor.x - prevCursor.x; SetP2ResizeInteger (winSize, p2.x, p2.y); break; case OVER_UPPER_LINE: p1.y+= cursor.y - prevCursor.y; SetP1ResizeInteger (winSize, p1.x, p1.y); break; case OVER_ORIENTER: or_p2.x= cursor.x; or_p2.y= cursor.y; SetRotation (atan2f((float) (or_p1.y - or_p2.y), (float) (or_p2.x - or_p1.x))); break; case OVER_UL_CORNER: case OVER_BR_CORNER: p1.x+= cursor.x - prevCursor.x; p1.y+= cursor.y - prevCursor.y; SetP1MoveInteger (winSize, p1.x, p1.y); break; } return true; } return false; } // Painting void CVisibleNormROI::OnPaint (const cv::Size& winSize, CIplImage *pImg) { Lock (); OnPaintRec (winSize, pImg); Unlock(); } void CVisibleNormROI::OnPaintRec (const cv::Size& winSize, CIplImage *pImg) { TNormROIListIterator i; for(i= m_childROIs.begin(); i != m_childROIs.end(); ++i) { CVisibleNormROI* pChild= dynamic_cast(*i); assert (pChild); pChild->OnPaintRec (winSize, pImg); } OnPaint0 (winSize, pImg); } void CVisibleNormROI::OnPaint0 (const cv::Size& winSize, CIplImage *pImg) { int thickness; CvPoint p1, p2; GetP1P2Integer (winSize, p1, p2); if (m_cursorOver>= OVER_LEFT_LINE && m_cursorOver<= OVER_BR_CORNER) thickness= 3; else thickness= 1; cvRectangle (pImg->ptr(), p1, p2, cvScalar(m_degradation, 255-m_degradation, 255-m_degradation, 0), thickness, 4); // Affordances CvPoint pa, pb; pa.x= p1.x - thickness; pa.y= p1.y - thickness; pb.x= p1.x + thickness; pb.y= p1.y + thickness; cvRectangle (pImg->ptr(), pa, pb, cvScalar(m_degradation, 255-m_degradation, 255-m_degradation, 0), CV_FILLED ); pa.x= p2.x - thickness; pa.y= p2.y - thickness; pb.x= p2.x + thickness; pb.y= p2.y + thickness; cvRectangle (pImg->ptr(), pa, pb, cvScalar(m_degradation, 255-m_degradation, 255-m_degradation, 0), CV_FILLED ); GetDirectionSegment (winSize, p1, p2); if (m_showOrientation) { if (m_cursorOver== OVER_ORIENTER) thickness= 3; else thickness= 1; cvLine (pImg->ptr(), p1, p2, cvScalar(0, 255, 255, 0), thickness, CV_AA ); cvCircle(pImg->ptr(), p2, SELECTION_TOLERANCE, cvScalar(0, 255, 255, 0), thickness, CV_AA ); } }