/**************************************************************************** ** $Id: rs_infoarea.cpp 1892 2004-07-09 23:54:59Z andrew $ ** ** Copyright (C) 2001-2003 RibbonSoft. All rights reserved. ** ** This file is part of the qcadlib Library project. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid qcadlib Professional Edition licenses may use ** this file in accordance with the qcadlib Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.ribbonsoft.com for further details. ** ** Contact info@ribbonsoft.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "rs_infoarea.h" #include "rs_infoarea.h" #include "rs_math.h" #include "rs_debug.h" /** * Constructor. */ RS_InfoArea::RS_InfoArea() { } /** * Destructor. */ RS_InfoArea::~RS_InfoArea() {} /** * Adds a point to the internal list * * @param p co-ordinate of the point */ void RS_InfoArea::addPoint(const RS_Vector& p) { if (thePoints.empty()) { baseY = p.y; } thePoints.append(p); } /** * Resets the points. */ void RS_InfoArea::reset() { thePoints.clear(); area = 0.0; circumference = 0.0; } /** * Closes the polygon if it is not closed already. */ void RS_InfoArea::close() { if (isValid() && isClosed()==false) { thePoints.append(thePoints.first()); RS_DEBUG->print("RS_InfoArea::close: closed"); } } /** * @retval true If the area is closed (i.e. start point and end point are * identical) * @retval false Otherwise. */ bool RS_InfoArea::isClosed() { return (thePoints.first().distanceTo(thePoints.last())<1.0e-4); } /** * @retval true If the area is defined (i.e. there are at least 3 points) * @retval false If there are only two or less points. */ bool RS_InfoArea::isValid() { RS_DEBUG->print("RS_InfoArea::isValid: count: %d", thePoints.count()); return (thePoints.count()>2); } /** * Calculates the area and the circumference of the area. */ void RS_InfoArea::calculate() { area = 0.0; circumference = 0.0; RS_Vector ptFirst; RS_Vector p1; RS_Vector p2; // at least 3 points needed for an area if (isValid()) { ptFirst = thePoints.last(); thePoints.pop_back(); p1 = ptFirst; while (!thePoints.empty()) { p2 = thePoints.last(); thePoints.pop_back(); area += calcSubArea(p1, p2); circumference += p1.distanceTo(p2); //if (p1 != ptFirst) { // delete p1; //} p1 = p2; } area += calcSubArea(p1, ptFirst); circumference += p1.distanceTo(ptFirst); //delete p1; //delete ptFirst; } //thePoints.clear(); area = fabs(area); } /** * Calculates a sub area. * * @param p1 first point * @param p2 second point */ double RS_InfoArea::calcSubArea(const RS_Vector& p1, const RS_Vector& p2) { double width = p2.x - p1.x; double height = (p1.y - baseY) + (p2.y - baseY); return width * height / 2.0; } /*! Calculates a distance \param _p1 first point \param _p2 second point */ /*double RS_InfoArea::calcDistance(RS_Vector *_p1, RS_Vector *_p2) { return mtGetDistance(_p1->getX(), _p1->getY(), _p2->getX(), _p2->getY()); }*/ // EOF