/***************************************************************************
 *   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.             *
 ***************************************************************************/
#include "box.h"
#include "general/drawpixmap.h"
#include <qpixmap.h>
#include <qbrush.h>
#include <qimage.h>
#include <qcolor.h>
#include <qwidget.h>
#include "pointarray.h"
#include <QTextStream>
#include "polygon.h"
#include "general/setup.h"
#include "boxproperties.h"
#include "elementlist.h"
#include "fileformats/dxf.h"
#include "fileformats/gds.h"
#include "fileformats/oasis.h"
#include "fileformats/cif.h"
#include "fileformats/csv.h"
#include "fileformats/svg.h"
#include "fileformats/gerber.h"
#include "general/drawingfield.h"
#include "path.h"
#include "general/drc.h"


box::box()
        : element() {}

box::box(QRect r,shortSelect Array) {
    rect=r;
    p_select=Array;
    clean();
}

box::box(QRect r,int layer)
        : element() {
    rect=r;
    layerNum=layer;
    clean();
}

box::box(int x_,int y_, int b_, int h_,int layer)
        : element() {
    rect.setLeft(x_);
    rect.setTop(y_);
    rect.setHeight(h_+1);
    rect.setWidth(b_+1);
    layerNum=layer;
    //p_select=QBitArray(4);
    //int i;
    //for (i=0;i<4;i++) {
    //    p_select.clearBit(i);
    //}
    clean();
}

box::~box() {}

void box::clean() {
    int h;
    if (rect.left()>rect.right()) {
        h=rect.left();
        rect.setLeft(rect.right());
        rect.setRight(h);
    }
    if (rect.bottom()>rect.top()) {
        h=rect.top();
        rect.setTop(rect.bottom());
        rect.setBottom(h);
    }
}
//#include <QThread>
void box::paint(layoutImagePainter *e) {
//printf("box %d\n",QThread::currentThreadId () );
  //printf("box\n");
  if (layers::num[layerNum].visible) {
	if ((-rect.height()<e->drawPixelSize)&&(rect.width()<e->drawPixelSize)){
		if (e->detailLevel>3) return;
 		e->drawPixel(QPoint(rect.left(),rect.top()),layers::layerColor[layerNum]);
		}
	else
	{
	e->drawBox.setPoint(0,rect.left(),rect.top());
	e->drawBox.setPoint(1,rect.right(),rect.top());
    	e->drawBox.setPoint(2,rect.right(),rect.bottom());
    	e->drawBox.setPoint(3,rect.left(),rect.bottom());
    	e->drawBox.setPoint(4,rect.left(),rect.top());
	e->drawPolygon(&e->drawBox,layers::layerColor[layerNum],layers::num[layerNum].brushStyle);
	}
    }
}


void box::paintSelect(layoutImagePainter *e) {
    if (layers::num[layerNum].visible) {
        if (select) {
		if ((-rect.height()<e->drawPixelSize)&&(rect.width()<e->drawPixelSize)){
 		e->drawPixel(QPoint(rect.left(),rect.top()),setup::selectColor.rgb());
		}
	else {
	e->drawBox.setPoint(0,rect.left(),rect.top());
	e->drawBox.setPoint(1,rect.right(),rect.top());
    	e->drawBox.setPoint(2,rect.right(),rect.bottom());
    	e->drawBox.setPoint(3,rect.left(),rect.bottom());
    	e->drawBox.setPoint(4,rect.left(),rect.top());
	e->drawPolygon(&e->drawBox,setup::selectColor.rgb());
        }}
	else {
        QPoint p1(rect.left(),rect.top());
        QPoint p2(rect.left(),rect.bottom());
        QPoint p3(rect.right(),rect.top());
        QPoint p4(rect.right(),rect.bottom());
        if (p_select.testBit(0)) {
            e->drawLine(p1,p3,setup::selectColor.rgb());
        }
        if (p_select.testBit(1)) {
            e->drawLine(p4,p3,setup::selectColor.rgb());
        }
        if (p_select.testBit(2)) {
            e->drawLine(p2,p4,setup::selectColor.rgb());
        }
        if (p_select.testBit(3)) {
            e->drawLine(p1,p2,setup::selectColor.rgb());
        }
	}
    }
}


void box::paintSelected(layoutImagePainter *e) {
	if ((-rect.height()<e->drawPixelSize)&&(rect.width()<e->drawPixelSize)){
 		e->drawPixel(QPoint(rect.left(),rect.top()),setup::selectColor.rgb());
		}
	else {
	e->drawBox.setPoint(0,rect.left(),rect.top());
	e->drawBox.setPoint(1,rect.right(),rect.top());
    	e->drawBox.setPoint(2,rect.right(),rect.bottom());
    	e->drawBox.setPoint(3,rect.left(),rect.bottom());
    	e->drawBox.setPoint(4,rect.left(),rect.top());
	e->drawPolygon(&e->drawBox,setup::selectColor.rgb());}
}

void box::paintNode(int node, layoutImagePainter *e){
	if (layers::num[layerNum].visible)
	if (getNode()==node) paintSelected(e);
}


void box::paintHighlighted(QPainter *po,strans  trans) {
    po->setPen(setup::highlightColor);
    QBrush br=layer::getBrush(setup::highlightBrush);
    br.setColor(setup::highlightColor);
    po->setBrush(br);
    po->drawPolygon(convert(rect,trans));
    //paintHighlightedBackground(po,trans );
}

void box::paintHighlighted(QPainter *po,strans trans,QPoint p_) {
  po->setPen(setup::highlightColor);
  QBrush br=layer::getBrush(setup::highlightBrush);
  br.setColor(setup::highlightColor);
  po->setBrush(br);
  int x,y;
  uint i;
  QPoint p[5];
  p[1]=QPoint(rect.left(),rect.top());
  p[2]=QPoint(rect.left(),rect.bottom());
  p[3]=QPoint(rect.right(),rect.top());
  p[4]=QPoint(rect.right(),rect.bottom());
  QPoint phelp;
  for (i=1;i<5;i++) {
	if (p[i]==p_){
		phelp=convert(p[i],trans);
		x=phelp.x();y=phelp.y();
		po->drawLine(x-1,y-1,x+1,y+1);
		po->drawLine(x+1,y-1,x-1,y+1);
		po->drawLine(x,y-5,x,y+5);
		po->drawLine(x-5,y,x+5,y);
		}}
}

void box::paintSize(QPainter *po,strans  trans_,double uunits){
}

void box::paintDistance(QPainter *po,strans  trans_, double uunits,element *e) {
}

void box::paintInfo(QPoint *min,QPoint *max,uint *count)const{
   (*count)++;
    if (rect.left()<min->x()) {
        min->setX(rect.left());
    }
    if (rect.bottom()<min->y()) {
        min->setY(rect.bottom());
    }
    if (rect.right()>max->x()) {
        max->setX(rect.right());
    }
    if (rect.top()>max->y()) {
        max->setY(rect.top());
  }
}

void box::fSelect(QRect select_) {
    if (layers::num[layerNum].visible) {
        QPoint p1(rect.left(),rect.top());
        QPoint p2(rect.left(),rect.bottom());
        QPoint p3(rect.right(),rect.top());
        QPoint p4(rect.right(),rect.bottom());
        if (pointInRect(p1,select_)) {
            select=true;
        }
        if (pointInRect(p2,select_)) {
            select=true;
        }
        if (pointInRect(p3,select_)) {
            select=true;
        }
        if (pointInRect(p4,select_)) {
            select=true;
        }
        if (select) {
            clearAllPSelect();
        }
    }
}

void box::fAllSelect(QRect select_) {
    if (layers::num[layerNum].visible) {
        QPoint p1(rect.left(),rect.top());
        QPoint p2(rect.left(),rect.bottom());
        QPoint p3(rect.right(),rect.top());
        QPoint p4(rect.right(),rect.bottom());
	bool b=true;
        if (!pointInRect(p1,select_)) {
            b=false;
        }
        if (!pointInRect(p2,select_)) {
            b=false;
        }
        if (!pointInRect(p3,select_)) {
            b=false;
        }
        if (!pointInRect(p4,select_)) {
            b=false;
        }
        if (b) {
	    select=true;
            clearAllPSelect();
        }
    }
}

void box::fDeselect(QRect select_) {
    if (layers::num[layerNum].visible) {
        QPoint p1(rect.left(),rect.top());
        QPoint p2(rect.left(),rect.bottom());
        QPoint p3(rect.right(),rect.top());
        QPoint p4(rect.right(),rect.bottom());
        if (pointInRect(p1,select_)||
                pointInRect(p2,select_)||
                pointInRect(p3,select_)||
                pointInRect(p4,select_)) {
            select=false;
            clearAllPSelect();
        }
    }
}

void box::fAllDeselect(QRect select_) {
    if (layers::num[layerNum].visible) {
        QPoint p1(rect.left(),rect.top());
        QPoint p2(rect.left(),rect.bottom());
        QPoint p3(rect.right(),rect.top());
        QPoint p4(rect.right(),rect.bottom());
	bool b=true;
        if (!pointInRect(p1,select_)) {
            b=false;
        }
        if (!pointInRect(p2,select_)) {
            b=false;
        }
        if (!pointInRect(p3,select_)) {
            b=false;
        }
        if (!pointInRect(p4,select_)) {
            b=false;
        }
        if (b) {
	    select=false;
            clearAllPSelect();
        }
    }
}


void box::pSelect(QRect select_) {
    if (layers::num[layerNum].visible) {
        if (select) {
            setAllPSelect();
        }
        QPoint p1(rect.left(),rect.top());
        QPoint p2(rect.left(),rect.bottom());
        QPoint p3(rect.right(),rect.top());
        QPoint p4(rect.right(),rect.bottom());
        if (pointInRect(p1,select_)) {
            p_select.setBit(0);
            p_select.setBit(3);
        }
        if (pointInRect(p2,select_)) {
            p_select.setBit(2);
            p_select.setBit(3);
        }
        if (pointInRect(p3,select_)) {
            p_select.setBit(0);
            p_select.setBit(1);
        }
        if (pointInRect(p4,select_)) {
            p_select.setBit(1);
            p_select.setBit(2);
        }
        bool b=true;
        int i;
        for (i=0;i<4;i++) {
            b=b&&p_select.testBit(i);
        }
        if (b) {
            clearAllPSelect();
            select=true;
        }
    }
}

void box::pDeselect(QRect select_) {
    if (layers::num[layerNum].visible) {
        if (select) {
            select=false;
            setAllPSelect();
        }
        QPoint p1(rect.left(),rect.top());
        QPoint p2(rect.left(),rect.bottom());
        QPoint p3(rect.right(),rect.top());
        QPoint p4(rect.right(),rect.bottom());
        if (pointInRect(p1,select_)) {
            p_select.clearBit(0);
            p_select.clearBit(3);
        }
        if (pointInRect(p2,select_)) {
            p_select.clearBit(2);
            p_select.clearBit(3);
        }
        if (pointInRect(p3,select_)) {
            p_select.clearBit(0);
            p_select.clearBit(1);
        }
        if (pointInRect(p4,select_)) {
            p_select.clearBit(1);
            p_select.clearBit(2);
        }
        bool b=true;
        int i;
        for (i=0;i<4;i++) {
            b=b&&p_select.testBit(i);
        }
        if (b) {
            clearAllPSelect();
            select=true;
        }
    }
}

void box::minimum(QPoint *pos) {
    if (rect.left()<pos->x()) {
        pos->setX(rect.left());
    }
    if (rect.bottom()<pos->y()) {
        pos->setY(rect.bottom());
    }
}

void box::maximum(QPoint *pos) {
    if (rect.right()>pos->x()) {
        pos->setX(rect.right());
    }
    if (rect.top()>pos->y()) {
        pos->setY(rect.top());
    }
}

void box::minimumSelect(QPoint *pos) {
  if (select) minimum(pos);
  else {
	if (p_select.testBit(0)) {
		if (rect.left()<pos->x()) 
        		pos->setX(rect.left());
   		 if (rect.top()<pos->y()) 
    		    pos->setY(rect.top());
		}
	if (p_select.testBit(1)) {
		if (rect.right()<pos->x()) 
        		pos->setX(rect.right());
   		 if (rect.bottom()<pos->y()) 
    		    pos->setY(rect.bottom());
		}
	if (p_select.testBit(2)) {
		if (rect.left()<pos->x()) 
        		pos->setX(rect.left());
   		 if (rect.bottom()<pos->y()) 
    		    pos->setY(rect.bottom());
		}
	if (p_select.testBit(3)) {
		if (rect.left()<pos->x()) 
        		pos->setX(rect.left());
   		 if (rect.bottom()<pos->y()) 
    		    pos->setY(rect.bottom());
		}
	}
}

void box::maximumSelect(QPoint *pos) {
  if (select) maximum(pos);
  else {
	if (p_select.testBit(0)) {
		if (rect.right()>pos->x()) 
			pos->setX(rect.right());
    		if (rect.top()>pos->y())
        		pos->setY(rect.top());
		}
	if (p_select.testBit(1)) {
		if (rect.right()>pos->x()) 
			pos->setX(rect.right());
    		if (rect.top()>pos->y())
        		pos->setY(rect.top());
		}
	if (p_select.testBit(2)) {
		if (rect.right()>pos->x()) 
			pos->setX(rect.right());
    		if (rect.bottom()>pos->y())
        		pos->setY(rect.bottom());
		}
	if (p_select.testBit(3)) {
		if (rect.left()>pos->x()) 
			pos->setX(rect.left());
    		if (rect.top()>pos->y())
        		pos->setY(rect.top());
		}
	}
}



void box::clearAllPSelect() {
    int i;
    for (i=0;i<4;i++) {
        p_select.clearBit(i);
    }
}

void box::setAllPSelect() {
    int i;
    for (i=0;i<4;i++) {
        p_select.setBit(i);
    }
}

void box::invertSelect(){
 if (select) {select=false; return;}
 bool b=false;
 int i;
    for (i=0;i<4;i++) {
	if (p_select.testBit(i)) {
		p_select.clearBit(i);
		b=true;	
		}
	else {
        	p_select.setBit(i);
	}
    }
 if (!b) {
	clearAllPSelect();
	select=true;
	}
}

void box::saveSOURCE( source *o){
}

void box::saveGDS(gds *g) {
    QPoint point;
if (!setup::gdsBoxToPolygon){
    // box
    g->write->writeUInt16(4);
    g->write->writeUInt8(0x2D);
    g->write->writeUInt8(0);
}
else
{
    // polygon (boundery)
    g->write->writeUInt16(4);
    g->write->writeUInt8(8);
    g->write->writeUInt8(0);
}
    //layer
    g->write->writeUInt16(6);
    g->write->writeUInt8(0x0D);
    g->write->writeUInt8(2);
    if (!setup::gdsMapLayer)
    	g->write->writeInt16((qint16)layerNum);
    else
	g->write->writeInt16((qint16)layers::num[layerNum].mapToLayer);
if (!setup::gdsBoxToPolygon){
    //boxtype
    g->write->writeUInt16(6);
    g->write->writeUInt8(0x2E);
    g->write->writeUInt8(2);
    if (!setup::gdsMapLayer)
    	g->write->writeInt16((qint16)datatype);
    else
	g->write->writeInt16((qint16)layers::num[layerNum].getMapToDatatype(datatype));
}
else {
    //datatype
    g->write->writeUInt16(6);
    g->write->writeUInt8(0x0E);
    g->write->writeUInt8(2);
        if (!setup::gdsMapLayer)
    	g->write->writeInt16((qint16)datatype);
    else
	g->write->writeInt16((qint16)layers::num[layerNum].getMapToDatatype(datatype));
}
    //xy 
    g->write->writeUInt16((5*2*4)+4);
    g->write->writeUInt8(0x10);
    g->write->writeUInt8(3);
    g->write->writeInt32((qint32)rect.left());g->write->writeInt32((qint32)rect.top());
    g->write->writeInt32((qint32)rect.right());g->write->writeInt32((qint32)rect.top());
    g->write->writeInt32((qint32)rect.right());g->write->writeInt32((qint32)rect.bottom());
    g->write->writeInt32((qint32)rect.left());g->write->writeInt32((qint32)rect.bottom());
    g->write->writeInt32((qint32)rect.left());g->write->writeInt32((qint32)rect.top());
	//properties
	saveGDSProperty(g);
    // endel
    g->write->writeUInt16(4);
    g->write->writeUInt8(0x11);
    g->write->writeUInt8(0);
    /*(*g->streamPtr)<<(quint16) 4<<(quint8) 0x2D<<(quint8)0;  //box
    (*g->streamPtr)<<(quint16) 6<<(quint8) 0x0D<<(quint8)2<<(qint16)(layer_nr);  //layer
    (*g->streamPtr)<<(quint16) 6<<(quint8) 0x2E<<(quint8)2<<(qint16)(datatype);  //boxtype
    (*g->streamPtr)<<(quint16) ((5*2*4)+4)<<(quint8) 0x10<<(quint8)3;  //XY
    (*g->streamPtr)<<(qint32)(rect.left())<<(qint32)(rect.top());
    (*g->streamPtr)<<(qint32)(rect.right())<<(qint32)(rect.top());
    (*g->streamPtr)<<(qint32)(rect.right())<<(qint32)(rect.bottom());
    (*g->streamPtr)<<(qint32)(rect.left())<<(qint32)(rect.bottom());
    (*g->streamPtr)<<(qint32)(rect.left())<<(qint32)(rect.top());
    (*g->streamPtr)<<(quint16) 4<<(quint8) 0x11<<(quint8)0;  //endel*/
    g->count();
}

void box::save(QDataStream *stream){
	(*stream)<<(qint8)(1);
	(*stream)<<(qint16)(layerNum);
	(*stream)<<(qint16)(datatype);
	(*stream)<<(qint32)(rect.left());
	(*stream)<<(qint32)(rect.top());
	(*stream)<<(qint32)(rect.width());
	(*stream)<<(qint32)(rect.height());
}

void box::saveSelect(QDataStream *stream){
  if (select){
	save(stream);
  }
}

void box::saveDXF(dxf *d) {
QString s;
d->writeEntry(0,"POLYLINE");
d->writeEntry(100,"AcDb2dPolyline");
//dxf::writeEntry(st,8,setup::layer->nr[layer_nr].name);
d->writeLayer(layerNum);
d->writeEntry(66,"   1");
d->writeEntry(70,"   1");
d->writeEntry(40,"0.0");
d->writeEntry(41,"0.0");
d->writeEntry(0,"VERTEX");
d->writeEntry(100,"AcDbVertex");
d->writeEntry(100,"AcDb2dVertex");
d->writeEntry(8,layers::num[layerNum].name);
d->writeEntry(10,s.setNum(rect.left()*d->df->userunits));
d->writeEntry(20,s.setNum(rect.top()*d->df->userunits));
d->writeEntry(0,"VERTEX");
d->writeEntry(100,"AcDbVertex");
d->writeEntry(100,"AcDb2dVertex");
d->writeEntry(8,layers::num[layerNum].name);
d->writeEntry(10,s.setNum(rect.right()*d->df->userunits));
d->writeEntry(20,s.setNum(rect.top()*d->df->userunits));
d->writeEntry(0,"VERTEX");
d->writeEntry(100,"AcDbVertex");
d->writeEntry(100,"AcDb2dVertex");
d->writeEntry(8,layers::num[layerNum].name);
d->writeEntry(10,s.setNum(rect.right()*d->df->userunits));
d->writeEntry(20,s.setNum(rect.bottom()*d->df->userunits));
d->writeEntry(0,"VERTEX");
d->writeEntry(100,"AcDbVertex");
d->writeEntry(100,"AcDb2dVertex");
d->writeEntry(8,layers::num[layerNum].name);
d->writeEntry(10,s.setNum(rect.left()*d->df->userunits));
d->writeEntry(20,s.setNum(rect.bottom()*d->df->userunits));
d->writeEntry(0,"VERTEX");
d->writeEntry(100,"AcDbVertex");
d->writeEntry(100,"AcDb2dVertex");
d->writeEntry(8,layers::num[layerNum].name);
d->writeEntry(10,s.setNum(rect.left()*d->df->userunits));
d->writeEntry(20,s.setNum(rect.top()*d->df->userunits));
d->writeEntry(0,"SEQEND");
//dxf::writeEntry(st,8,setup::layer->nr[layer_nr].name);
}

#ifdef USE_3d
void box::saveDXF3d(dxf3d*d){
if (select||d->renderAll())
	d->save(layerNum,rect);
}
#endif

void box::saveSVG(svg *s){
*(s->str)<<"<rect ";
s->savePos("x",rect.left());
s->savePos("y",-rect.top());
s->savePos("width",rect.right()-rect.left());
s->savePos("height",rect.top()-rect.bottom());
if (layers::num[layerNum].getStyle()==0){
	s->saveValue("stroke",layers::num[layerNum].pen.color().name());
	s->saveValue("fill","none");
}
else 
	s->saveValue("fill",layers::num[layerNum].pen.color().name());
*(s->str)<<"/>"<<s->endOfLine;
}

void box::saveOASIS( oasis *o){
  int oasisDatatype=datatype;
  int oasisLayer=layerNum;
  if (!setup::oasisMapLayer){
	oasisLayer=layers::num[layerNum].mapToLayer;
	oasisDatatype=layers::num[layerNum].getMapToDatatype(datatype);
  }
  o->count();
  if (!o->modal.absoluteMode){o->setModalAbsoluteMode();}
  qint8 info_byte=0;
  if (oasisLayer!=o->modal.layer) info_byte+=1;
  if (oasisDatatype!=o->modal.datatype) info_byte+=2;
  if (rect.left()!=o->modal.geometry_x) info_byte+=16;
  if (rect.bottom()!=o->modal.geometry_y) info_byte+=8;
  if (rect.top()-rect.bottom()!=o->modal.geometry_h) info_byte+=32;
  if (rect.right()-rect.left()!=o->modal.geometry_w) info_byte+=64;
  if (rect.right()-rect.left()==rect.top()-rect.bottom()) {info_byte+=128;info_byte=info_byte&(255-32);}
  o->writeUnsignedInteger((uint)20);
  o->writeRaw(info_byte);
  if (info_byte&1) {
	o->modal.layer=oasisLayer;
	o->writeUnsignedInteger((uint)o->modal.layer);
	}
  if (info_byte&2) {
	o->modal.datatype=oasisDatatype;
	o->writeUnsignedInteger((uint)oasisDatatype);
	}
  if (info_byte&64) {
	o->modal.geometry_w=rect.right()-rect.left();
	o->writeUnsignedInteger((uint)o->modal.geometry_w);
	}
  if (info_byte&128) o->modal.geometry_h=o->modal.geometry_w;
  if (info_byte&32) {
	o->modal.geometry_h=rect.top()-rect.bottom();
	o->writeUnsignedInteger((uint)o->modal.geometry_h);
	}
  if (info_byte&16) {
	o->modal.geometry_x=rect.left();
	o->writeSignedInteger(o->modal.geometry_x);
	}
  if (info_byte&8) {
	o->modal.geometry_y=rect.bottom();
	o->writeSignedInteger(o->modal.geometry_y);
	}
  saveOASISProperty(o);
}
void box::saveCIF( cif *c){
  QString s="L "+layers::num[layerNum].name;
  c->writeEntry(s);
  s="B ";
  QString s1;
  s+=s1.setNum(rect.right()-rect.left())+" ";
  s+=s1.setNum(rect.top()-rect.bottom())+" ";
  s+=s1.setNum((rect.right()+rect.left())/2)+",";
  s+=s1.setNum((rect.top()+rect.bottom())/2);
  c->writeEntry(s);
}

void box::saveCSV( csv *c){
  pointArray pa;
  pa<<QPoint(rect.right(),rect.top());
  pa<<QPoint(rect.right(),rect.bottom());
  pa<<QPoint(rect.left(),rect.bottom());
  pa<<QPoint(rect.left(),rect.top());
  pa<<QPoint(rect.right(),rect.top());
  if (select) c->savePointArray(pa);
}

void box::saveGerber( gerber *g){
 if (g->saveLayer!=layerNum) return;
  g->write(g->aperturRect(rect.right()-rect.left(),rect.top()-rect.bottom()),QPoint((rect.right()+rect.left())/2,(rect.top()+rect.bottom())/2),3);
}

void box::saveEPS( eps *e){
}

int box::saveEPSCount(){
  int count=29+5*(16)+9+7+10;
  return count;
}

void box::saveODB( odb *g){
#ifdef netlistutility
#endif
}

void box::moveSelect(QPoint pos) {
    if (select)
        rect.translate(pos.x(),pos.y());
    else {
        if (p_select.testBit(0))
            rect.setTop(rect.top()+pos.y());
        if (p_select.testBit(1))
            rect.setRight(rect.right()+pos.x());
        if (p_select.testBit(2))
            rect.setBottom(rect.bottom()+pos.y());
        if (p_select.testBit(3))
            rect.setLeft(rect.left()+pos.x());
        if (rect.width()<0) {
            int h=rect.right();
            bool b=p_select.testBit(1);
            rect.setRight(rect.left());
            p_select.setBit(1,p_select.testBit(3));
            rect.setLeft(h);
            p_select.setBit(3,b);
        }
        if (rect.height()>0) {
            int h=rect.top();
            bool b=p_select.testBit(0);
            rect.setTop(rect.bottom());
            p_select.setBit(0,p_select.testBit(2));
            rect.setBottom(h);
            p_select.setBit(2,b);
        }
    clean();
    }
}

void box::move(QPoint pos) {
    rect.translate(pos.x(),pos.y());
}

void box::resize(double size) {
    rect.setTop(element::runden((double)(rect.top())*size));
    rect.setLeft(element::runden((double)(rect.left())*size));
    rect.setRight(element::runden((double)(rect.right())*size));
    rect.setBottom(element::runden((double)(rect.bottom())*size));
}

void box::resize(double size,int mod, bool *b){
if (rect.left() %mod!=0) *b=true;
if (rect.top() %mod!=0) *b=true;
if (rect.right() %mod!=0) *b=true;
if (rect.bottom() %mod!=0) *b=true;
resize(size);
}


void box::sizeadjustSelect(int value) {
    if (select) {
        rect.setTop(rect.top()+value);
        rect.setLeft(rect.left()-value);
        rect.setRight(rect.right()+value);
        rect.setBottom(rect.bottom()-value);
        if ((rect.top()-rect.bottom())<0) {
            rect.setHeight(0);
        }
        if ((rect.right()-rect.left())<0) {
            rect.setWidth(0);
        }
    }
}

void box::sizeadjustSelect(int valueX, int valueY) {
    if (select) {
        rect.setTop(rect.top()+valueY);
        rect.setLeft(rect.left()-valueX);
        rect.setRight(rect.right()+valueX);
        rect.setBottom(rect.bottom()-valueY);
        if ((rect.top()-rect.bottom())<0) {
            rect.setHeight(0);
        }
        if ((rect.right()-rect.left())<0) {
            rect.setWidth(0);
        }
    }
}

polygon* box::convertToPolygon()const {
    pointArray points(5);
    points.setPoint(0,rect.left(),rect.top());
    points.setPoint(1,rect.left(),rect.bottom());
    points.setPoint(2,rect.right(),rect.bottom());
    points.setPoint(3,rect.right(),rect.top());
    points.setPoint(4,rect.left(),rect.top());
    polygon *p=new polygon(points,layerNum);
    p->datatype=datatype;
    p->property=property;
    return p;
}

bool box::pointInsideElement(QPoint p){
  if (p.x()<rect.left()) return false;
  if (p.x()>rect.right()) return false;
  if (p.y()<rect.bottom()) return false;
  if (p.y()>rect.top()) return false;
  return true;
}

elementList* box::convertToMesh(int width , int spaceing) { 
 if (!select) return NULL;
 if (!correct()) return NULL;
 elementList *b,*a=NULL;
 pointArray points(6);
 int w2=width/2;
 points.setPoint(0,rect.left()+w2,(rect.top()+rect.bottom())/2);
 points.setPoint(1,rect.left()+w2,rect.top()-w2);
 points.setPoint(2,rect.right()-w2,rect.top()-w2);
 points.setPoint(3,rect.right()-w2,rect.bottom()+w2);
 points.setPoint(4,rect.left()+w2,rect.bottom()+w2);
 points.setPoint(5,rect.left()+w2,(rect.top()+rect.bottom())/2);
 element *c;
 c=new path(points,layerNum);
 c->setWidth(width);
 c->setCap(0);
 b=new elementList();
 b->thisElement=c;
 b->nextElement=a;
 c=NULL;
 a=b;
 int sr=width+spaceing;
 int start=round(rect.left()/sr)*sr;
 while (start<=rect.left()+w2) start+=sr;
 for (int i=start;i<rect.right()-w2;i+=sr){
	points.resize(2);
	points.setPoint(0,i,rect.bottom()+w2);
 	points.setPoint(1,i,rect.top()-w2);
	c=new path(points,layerNum);
	c->setWidth(width);
	c->setCap(setup::defaultPathCap);
	b=new elementList();
	b->thisElement=c;
	b->nextElement=a;
	c=NULL;
	a=b;
   }
 start=round(rect.bottom()/sr)*sr;
 while (start<=rect.bottom()+w2) start+=sr;
 for (int i=start;i<rect.top()-w2;i+=sr){
	points.resize(2);
	points.setPoint(0,rect.left()+w2,i);
 	points.setPoint(1,rect.right()-w2,i);
	c=new path(points,layerNum);
	c->setWidth(width);
	c->setCap(setup::defaultPathCap);
	b=new elementList();
	b->thisElement=c;
	b->nextElement=a;
	c=NULL;
	a=b;
   }
  return a;

}

bool box::correct() {
    if (rect.left()==rect.right())
        return false;
    if (rect.top()==rect.bottom())
        return false;
    return true;
}

void box::roundSelect(int i) {
    if (select) {
        rect.setTopLeft(round(rect.topLeft(),i));
        rect.setBottomRight(round(rect.bottomRight(),i));
        clean();
    }
}

double box::areaSelected() {
    double a=((double)abs(rect.left()-rect.right())*(double)abs(rect.top()-rect.bottom()));
    return a;
}

double box::circumferenceSelected(){
   double a=((double)abs(rect.left()-rect.right())+(double)abs(rect.top()-rect.bottom()));
   a=a*2;
    return a;
}

double box::nearestDistance(QPoint p) {
   if (layers::num[layerNum].visible) {
    QPoint p1(rect.left(),rect.top());
    QPoint p2(rect.left(),rect.bottom());
    QPoint p3(rect.right(),rect.top());
    QPoint p4(rect.right(),rect.bottom());
    double dis=distance(p1,p);
    double d=distance(p2,p);
    if (d<dis) {
        dis=d;
    };
    d=distance(p3,p);
    if (d<dis) {
        dis=d;
    };
    d=distance(p4,p);
    if (d<dis) {
        dis=d;
    };
    return dis;}
  else return 1.1E99;
}
double box::nearestDistance(const QPoint p, QPoint *p_)const {
   if (layers::num[layerNum].visible) {
    QPoint p1(rect.left(),rect.top());
    QPoint p2(rect.left(),rect.bottom());
    QPoint p3(rect.right(),rect.top());
    QPoint p4(rect.right(),rect.bottom());
    double dis=distance(p1,p);
    double d=distance(p2,p);
    *p_=p1;
    if (d<dis) {
        dis=d;
	*p_=p2;
    };
    d=distance(p3,p);
    if (d<dis) {
        dis=d;
	*p_=p3;
    };
    d=distance(p4,p);
    if (d<dis) {
        dis=d;
	*p_=p4;
    };
    return dis;}
  else return 1.1E99;
}

double box::nearestLine(QPoint p,QPoint *p_,int) {
if (layers::num[layerNum].visible) {
    QPoint p1(p.x(),rect.top());
    QPoint p2(rect.left(),p.y());
    QPoint p3(rect.right(),p.y());
    QPoint p4(p.x(),rect.bottom());
    double dis=distance(p1,p);
    double d=distance(p2,p);
    *p_=p1;
    if (d<dis) {
        dis=d;
	*p_=p2;
    };
    d=distance(p3,p);
    if (d<dis) {
        dis=d;
	*p_=p3;
    };
    d=distance(p4,p);
    if (d<dis) {
        dis=d;
	*p_=p4;
    };
    if (p_->x()>rect.right()) return 1.1E99;
    if (p_->x()<rect.left()) return 1.1E99;
    if (p_->y()>rect.top()) return 1.1E99;
    if (p_->y()<rect.bottom()) return 1.1E99;
    return dis;}
  else return 1.1E99;
}

double box::nearestMiddle(QPoint p,QPoint *p_,int) {
   if (layers::num[layerNum].visible) {
    QPoint p1((rect.left()+rect.right())/2,rect.top());
    QPoint p2(rect.left(),(rect.bottom()+rect.top())/2);
    QPoint p3(rect.right(),(rect.bottom()+rect.top())/2);
    QPoint p4((rect.left()+rect.right())/2,rect.bottom());
    double dis=distance(p1,p);
    double d=distance(p2,p);
    *p_=p1;
    if (d<dis) {
        dis=d;
	*p_=p2;
    };
    d=distance(p3,p);
    if (d<dis) {
        dis=d;
	*p_=p3;
    };
    d=distance(p4,p);
    if (d<dis) {
        dis=d;
	*p_=p4;
    };
    return dis;}
  else return 1.1E99;
}

double box::nearestCenter(QPoint p,QPoint *p_,int){
if (layers::num[layerNum].visible) {
  *p_=QPoint((rect.left()+rect.right())/2,(rect.top()+rect.bottom())/2);
  return distance(*p_,p);}
else return 1.1E99; 
return 0;
}

bool box::showProperties(elementList *el,drawingField * d,bool ){
  boxproperties b(d->userunits);
  b.setElement(el->thisElement->getBox());
  b.show();
  int i=b.exec();
  b.hide();
  switch (i) {
  case QDialog::Rejected :
  	return false;
  case QDialog::Accepted :
  	clean();
  	return false;
  case 2 :
  	return true;
  case 3 :
        {
	elementList *e;
	e=new elementList();
	e->nextElement=el->nextElement;
	e->thisElement=convertToPolygon();
	el->nextElement=e;
	return true;
	}
  }
  return false;
}

bool box::identicalStructure(element *e){ 
if (e->isBox()) {
	box *b=reinterpret_cast<box(*)>(e);
	if ((*b)%(*this)) return true;
	}
return false;
}

bool box::identical(element *e){
if (e->isBox()) {
	box *b=reinterpret_cast<box(*)>(e);
	if ((*b)==(*this)) return true;
	}
return false;
}

void  box::findEdge(QPoint p1, QPoint p2,int layer,char dir,int *result){
//printf("box start %d\n",dir);
if (layer!=layerNum) return;
switch(dir){
	case 0:
		//printf("box %d %d %d\n",rect.right(),(*result),p1.x());
		if ((rect.top()>p2.y())&&(rect.bottom()<p1.y()))
		if ((rect.right()>(*result))&&(rect.right()<p1.x()))
			*result=rect.right();
		break;
	case 1:
		//printf("box %d %d %d\n",rect.top(),(*result),p1.y());
		if ((rect.left()<p1.x())&&(rect.right()>p2.x()))
		if ((rect.top()>(*result))&&(rect.top()<p1.y()))
			*result=rect.top();
		break;
	case 2:
		if ((rect.top()>p2.y())&&(rect.bottom()<p1.y()))
		if ((rect.left()<(*result))&&(rect.left()>p2.x()))
			*result=rect.left();
		break;
	case 3:
		if ((rect.left()<p1.x())&&(rect.right()>p2.x()))
		if ((rect.bottom()<(*result))&&(rect.bottom()>p2.y()))
			*result=rect.bottom();
		break;
}
}

void box::lineDistanceLayer(QPoint p1,QPoint p2, int *left,int *right,int layer, QPoint min, QPoint max){
    if (layer!=layerNum) return;
    if (max.x()<rect.left())return ;
    if (min.x()>rect.right())return ;
    if (max.y()<rect.bottom())return ;
    if (min.y()>rect.top())return ;
    pointArray points(5);
    points.setPoint(0,rect.left(),rect.top());
    points.setPoint(1,rect.left(),rect.bottom());
    points.setPoint(2,rect.right(),rect.bottom());
    points.setPoint(3,rect.right(),rect.top());
    points.setPoint(4,rect.left(),rect.top());
    points.lineDistance(p1,p2,left,right);
}

bool operator== (const box &b1,const box &b2){
if (b1.layerNum!=b2.layerNum) return false;
if (b1.datatype!=b2.datatype) return false;
if (b1.rect.left()!=b2.rect.left()) return false;
if (b1.rect.right()!=b2.rect.right()) return false;
if (b1.rect.top()!=b2.rect.top()) return false;
if (b1.rect.bottom()!=b2.rect.bottom()) return false;
return true;
}

bool operator% (const box &b1,const box &b2){
if (b1.layerNum!=b2.layerNum) return false;
if (b1.datatype!=b2.datatype) return false;
if (b1.rect.left()-b1.rect.right()!=b2.rect.left()-b2.rect.right()) return false;
if (b1.rect.top()-b1.rect.bottom()!=b2.rect.top()-b2.rect.bottom()) return false;
return true;
}


double box::length(){
return abs(rect.right()-rect.left())*2+abs(rect.top()-rect.bottom())*2;
}

bool box::pointOnLayer(QPoint p,int layer){
if (layer!=layerNum) return false;
if (p.y()<rect.bottom()) return false;
if (p.y()>rect.top()) return false;
if (p.x()<rect.left()) return false;
if (p.x()>rect.right()) return false;
return true;
}

//virtual int minSize() { int a=rect.right()-rect.left(); int b=rect.top()-rect.bottom(); if (a>b) return b; else return a;}
bool box::drcMinSize(int val,drc *DRC,bool ){
}

bool box::drcMinDistance(int dis,drc *DRC,element *e){
}


bool box::drcEnclosure(int dis,drc *DRC,element *e){
}

bool box::drcOnGrid(int grid,int layer){
 if (layerNum!=layer) return true;
 pointArray pointarray=getPoints();
 for(int i=0;i<pointarray.size();i++)
	  if (round(pointarray.point(i),grid)!=pointarray.point(i)) return false;
 return true;
}

bool box::drcAngle(double a,drc *DRC){
if (a<90.0) return true;
DRC->reportError(QPoint(rect.left(),rect.top()),90.0);
return false;
}


void box::snapSelectGet(QHash<int,QPoint> *h){
     if (select) {
      
     } else {
        pointArray points(4);
	points.setPoint(0,rect.left(),rect.top());
	points.setPoint(1,rect.left(),rect.bottom());
	points.setPoint(2,rect.right(),rect.bottom());
	points.setPoint(3,rect.right(),rect.top());
	for (int i=(int)points.size()-1;i>=0;i--) {
	    {
	        QList<QPoint> l=h->values(points.point(i).x());
		if (!l.contains(points.point(i))) h->insertMulti(points.point(i).x(),points.point(i));
	    }
	}
     }
}

void box::snapSelectSnap(QHash<int,QPoint> *h,int radius){
  bool moved=false;
  if (p_select.testBit(0)||select){
    	    double snapdist=radius+1;
            bool snaped=false;
	    int pos=0;
	    for (int x=rect.left()-radius;x<=rect.right()+radius;++x){
		  QList<QPoint> l=h->values(x);
		  for (int k=l.size();k>0;--k){
		    if (l.at(k-1).x()-radius<rect.right())
		      if ((l.at(k-1).x()+radius>rect.left()))
			if (snapdist>abs(l.at(k-1).y()-rect.top())){
			  snapdist=abs(l.at(k-1).y()-rect.top());
			  snaped=true;
			  pos=l.at(k-1).y();
			}
		  }
	    }
	    if (snaped){
	      moved=true;
	      rect.setTop(pos);
	    }
  }
  if (p_select.testBit(1)||select){
    	    double snapdist=radius+1;
            bool snaped=false;
	    int pos=0;
	    for (int x=0;x<=radius;++x){
		  QList<QPoint> l=h->values(rect.right()+x);
		  if (x!=0) l<<h->values(rect.right()-x);
		  for (int k=l.size();k>0;--k){
		    if (l.at(k-1).y()-x<rect.top())
		      if ((l.at(k-1).y()+x>rect.bottom()))
			if (snapdist>x){
			  snapdist=x;
			  snaped=true;
			  pos=l.at(k-1).x();
			}
		  }
	    }
	    if (snaped){
	      moved=true;
	      rect.setRight(pos);
	    }
  }
        if (p_select.testBit(2)||select){
    	    double snapdist=radius+1;
            bool snaped=false;
	    int pos=0;
	    for (int x=rect.left()-radius;x<=rect.right()+radius;++x){
		  QList<QPoint> l=h->values(x);
		  for (int k=l.size();k>0;--k){
		    if (l.at(k-1).x()-radius<rect.right())
		      if ((l.at(k-1).x()+radius>rect.left()))
			if (snapdist>abs(l.at(k-1).y()-rect.bottom())){
			  snapdist=abs(l.at(k-1).y()-rect.bottom());
			  snaped=true;
			  pos=l.at(k-1).y();
			}
		  }
	    }
	    if (snaped){
	      moved=true;
	      rect.setBottom(pos);
	    }
  }
        if (p_select.testBit(3)||select){
    	    double snapdist=radius+1;
            bool snaped=false;
	    int pos=0;
	    for (int x=0;x<=radius;++x){
		  QList<QPoint> l=h->values(rect.left()+x);
		  if (x!=0) l<<h->values(rect.left()-x);
		  for (int k=l.size();k>0;--k){
		    if (l.at(k-1).y()-x<rect.top())
		      if ((l.at(k-1).y()+x>rect.bottom()))
			if (snapdist>x){
			  snapdist=x;
			  snaped=true;
			  pos=l.at(k-1).x();
			}
		  }
	    }
	    if (snaped){
	      moved=true;
	      rect.setLeft(pos);
	    }
	}

  if (moved) clean();
  moved=select;
  select=false;
  snapSelectGet(h);
  select=moved;
}



