/***************************************************************************
 *   Copyright (C) 2004 by Juergen Thies                                   *
 *   layout@juergenthies.de                                                *
 *                                                                         *
 *   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 2 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, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef POLYGON_H
#define POLYGON_H

#include "elements/element.h"
#include "general/drawpixmap.h"
#include <qbitarray.h>
#include "pointarray.h"
#include <QTextStream>
#include "strans.h"

/**
@author Juergen Thies
*/
class box;
class oasis;
class csv;
class polygon : public element
{
private:
int size;
void calcSize();
pointArray pointarray;
QBitArray p_select;
public:

    polygon(const pointArray points,const int layer);
    polygon(const pointArray points,const qint16 layer,const qint16 datatype_);
    polygon();
    polygon(polygon * p){
		pointarray=p->pointarray;
		layerNum=p->layerNum;
		p_select=p->p_select;
		select=p->select;
		size=p->size;
		property=p->property;
		datatype=p->datatype;
		};
    ~polygon();
virtual void paint(layoutImagePainter *e);
virtual void paintSelect(layoutImagePainter *e);
virtual void paintSelected(layoutImagePainter *e);
virtual void paintNode(int node, layoutImagePainter *e);
virtual void paintHighlighted(QPainter *,strans  ) ;
virtual void paintHighlighted(QPainter *,strans ,QPoint ) ;
virtual void paintSize(QPainter *,strans ,double uunits  );
virtual void paintDistance(QPainter *,strans  , double ,element *);
virtual void paintInfo(QPoint *,QPoint *,uint *)const;
virtual void fSelect(QRect select);
virtual void pSelect(QRect select);
virtual void fDeselect(QRect select);
virtual void pDeselect(QRect select);
virtual void fAllSelect(QRect select);
virtual void fAllDeselect(QRect select);
virtual void minimum(QPoint *pos);
virtual void maximum(QPoint *pos);
virtual void minimumSelect(QPoint *pos);
virtual void maximumSelect(QPoint *pos);
/*virtual int minSize();*/
virtual bool drcMinSize(int ,drc *,bool sharpAngles=true);
virtual bool drcMinDistance(int ,drc *,element *);
virtual bool drcEnclosure(int ,drc *,element *);
virtual bool drcOnGrid(int grid,int layer){
	if (layerNum!=layer) return true;
	for(int i=0;i<pointarray.size();i++)
	  if (round(pointarray.point(i),grid)!=pointarray.point(i)) return false;
	return true;}
virtual bool drcAngle90(drc *);
virtual bool drcAngle45(drc *);
virtual bool drcAngle(double,drc *);
virtual bool drcNotch(int ,drc *);
virtual bool hasHoles(){
  QList<pointArray> l=pointarray.seperate();
  if (l.size()>1) return true;
  return false;
}
virtual void deleteSelect();
virtual void saveSOURCE( source *);
virtual void saveGDS(gds *);
virtual void saveDXF(dxf *);
#ifdef USE_3d
virtual void saveDXF3d(dxf3d*);
#endif
virtual void saveSVG(svg *);
virtual void saveOASIS( oasis *);
virtual void saveSelect(QDataStream *);
virtual void save(QDataStream *);
virtual void saveCIF( cif *);
virtual void saveCSV( csv *);
virtual void saveGerber( gerber *);
virtual void saveODB( odb *);
virtual void saveEPS(eps *);
virtual int saveEPSCount();
virtual void moveSelect(QPoint pos);
virtual void move(QPoint pos);
virtual void resize(double size);
virtual void resize(double ,int, bool *);
virtual bool mergeSelect(polygon * p);

//virtual bool add(pointArray *array);
virtual box* convertToBox();
virtual polygon* convertToCircle() ;
virtual void mapSelect(strans m);
virtual void map(strans m);
virtual void clean();
virtual void sizeadjustSelect(int value);
virtual void sizeadjustSelect(int value1, int value2);
virtual void modifyCornersSelect(double value1,double value2);
void deletePoint(uint pos);
void addPoint(uint pos);
virtual bool correct();
virtual bool isPolygon()const{return true;}
virtual polygon* getPolygon(){return this;};
virtual elementList* cutSelect(QPoint p1, QPoint p2);
virtual elementList* convertToMesh(int width , int spaceing);
virtual void edgeRemoveSelect(int i);
virtual void cropSharpAnglesSelect(int i);
virtual void roundSelect(int i);
virtual double areaSelect(){if (select) {return areaSelected();} else return 0;}
virtual double areaSelected();
virtual double circumferenceSelect(){if (select) {return circumferenceSelected();} else return 0;}
virtual double circumferenceSelected();
virtual double nearestDistance(QPoint p);
virtual double nearestDistance(const QPoint,QPoint *)const;
virtual double nearestLine(QPoint,QPoint *,int) ;
virtual double nearestMiddle(QPoint,QPoint *,int) ;
virtual double nearestCenter(QPoint,QPoint *,int) ;
virtual bool pointInsideElement(QPoint);
virtual bool showProperties(elementList *, drawingField *,bool basicEditing);
private:
void mergeIn(pointArray *neu, int *pos, pointArray *parray, int *pos2, int *pos1, pointArray * cutpoint, pointArray * cutpos, pointArray *cutpara,bool dir,int nr);
void setAllPSelect();
void clearAllPSelect();
bool mergeBoolean(polygon * p);
//debug
public:
virtual void nextPoint();
//
virtual void invertSelect();
virtual void selectAll(){select=true;clearAllPSelect();}
virtual void selectVisible(){if (layers::num[layerNum].visible){select=true;clearAllPSelect();}}
virtual void deselectAll(){select=false;clearAllPSelect();}
virtual void selectLayer(int layer){if (layerNum==layer) selectAll();}
virtual void deselectLayer(int layer){if (layerNum==layer) deselectAll();}
virtual void countSelect(elementCount *c){if (select) {c->polygon++;} 
					else {
						for (int i=0;i<p_select.size()-1;i++){
							if (p_select.testBit(i))c->points++;}}}
virtual bool useLayer(int layer){if (layerNum==layer) return true; else return false;}
virtual void useLayer(QBitArray *b){b->setBit(layerNum);};
virtual bool isCircle(QPoint *p, int *radius);
virtual bool isCircle(){QPoint p; int r; return isCircle(&p,&r);}
virtual bool isSector(QPoint *p, int *radius, double *start,double *end);
virtual bool isSector(){QPoint p; int r; double start,end; return isSector(&p,&r,&start,&end);}
virtual pointArray getPoints(){return pointarray;}
virtual void setPoints(pointArray pa){pointarray=pa;p_select.resize(pointarray.size());clean();}
virtual void findEdge(QPoint p1, QPoint p2,int layer,char dir,int *result);
virtual void lineDistanceLayer(QPoint p1,QPoint p2, int *left,int *right,int layer, QPoint min, QPoint max);
pointArray toPolygon()const;
virtual bool pointOnLayer(QPoint p,int layer);
//direct access to array required for:
friend class polygonproperties;
friend class booleanHandler;
   virtual bool identical(element *);
   virtual bool identicalStructure(element *);
   friend bool operator% (const polygon &r1,const polygon &r2);
   friend bool operator== (const polygon &r1,const polygon &r2);
   friend bool operator&& (const polygon &r1,const polygon &r2);
   friend bool operator&& (const box &r1,const polygon &r2);
   friend bool operator&& (const polygon &r1,const txt &r2);
   friend bool operator&& (const path &r1,const polygon &r2);
virtual double length();
virtual void snapSelectGet(QHash<int,QPoint> *);
virtual void snapSelectSnap(QHash<int,QPoint> *,int radius);
};

#endif
