/***************************************************************************
 *   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.             *
 ***************************************************************************/
#define _USE_MATH_DEFINES
#include "element.h"
#include "general/drawpixmap.h"
#include "fileformats/gds.h"
#include "fileformats/oasis.h"
#include <QList>
#include <math.h>
#include "pointarray.h"
#include "elements/path.h"
#include "elements/polygon.h"
#include "elements/text.h"
#include "elements/cellref.h"
#include "elements/cellrefarray.h"
#include "elements/box.h"

int maxX=(1<<15)-5
	,maxY=(1<<15)-5
	,minX=-(1<<15)+5
	,minY=-(1<<15)+5;
/*const int maxX=600
	,maxY=500
	,minX=(50)
	,minY=(50);*/
	


element::element()
{
layerNum=1;
select=false;
datatype=0;
}


element::~element()
{
}

void element::addProperty(const QList<propertyItem> list){
   property<<list;

}

void element::addProperty(const propertyItem item){

   property<<item;
}

void element::saveGDSProperty(gds *g){
 for (int i=0;i<property.size();i++){
    int pnum=property.at(i).getNum();
	if (pnum<32768){
		// proatr
		g->write->writeUInt16(6);
		g->write->writeUInt8(43);
		g->write->writeUInt8(2);
		g->write->writeInt16((qint16)(pnum));
		// proval
		g->writeString(property.at(i).getValueString(),44);
	}
  }
     	

}

void element::saveOASISProperty( oasis *o){
 for (int i=0;i<property.size();i++){
    if (((property.at(i).nameType==propertyInt)&&(property.at(i).getNum()<32768))
		||(property.at(i).nameType!=propertyInt)){
			if (property.at(i).valueType!=propertyNone){
			   qint8 info_byte=0*16+4;
			   	o->writeUnsignedInteger((uint)28);
				o->writeRaw(info_byte);
				o->writeString(property.at(i).getString());
			}
			else {
			    qint8 info_byte=1*16+4;
				o->writeUnsignedInteger((uint)28);
				o->writeRaw(info_byte);
			    o->writeString(property.at(i).getString());
				o->writeUnsignedInteger((uint)12);
				o->writeString(property.at(i).getValueString());
			}
	}
  }
}

bool element::pointInRect(QPoint p,QRect rect){
if ((p.x()>=rect.left())&&(p.x()<=rect.right())&&(p.y()<=rect.top())&&(p.y()>=rect.bottom())){return true;}
else {return false;}
}



pointArray element::convert(const pointArray array,const strans trans){
//maxX=e->width();
//maxY=e->height();
int i=0,k;
char a=0,b=0;
pointArray array2;
QPoint point,point_;
array2.resize(3*array.size());
point=trans.mapDraw(array.point(i));
point_=point;
if (point.y()>=maxY){point.setY(maxY);a=0;}
else if (point.y()<=minY){point.setY(minY);a=6;}
else a=3;
if (point.x()>=maxX){point.setX(maxX);a+=3;}
else if (point.x()<=minX){point.setX(minX);a+=1;}
else a+=2;
array2.setPoint(0,point);
k=1;
for (i=1;i<array.size();i++){
        point=trans.mapDraw(array.point(i));
	if (point.y()>=maxY){b=0;}
	else if (point.y()<=minY){b=6;}
	else b=3;
	if (point.x()>=maxX){b+=3;}
	else if (point.x()<=minX){b+=1;}
	else b+=2;
	//printf("comp %d\n",(a*10+b));
	switch (a*10+b){
	case 77:
	case 99:
	case 11:
	case 33: break;
	case 55: array2.setPoint(k,point);k++;break;
	case 78:
	case 88:
	case 98: array2.setPoint(k,point.x(),minY);k++;break;
	case 12:
	case 22:
	case 32: array2.setPoint(k,point.x(),maxY);k++;break;
	case 74:
	case 14:
	case 44: array2.setPoint(k,minX,point.y());k++;break;
	case 96:
	case 36:
	case 66: array2.setPoint(k,maxX,point.y());k++;break;
	case 17:
	case 97:
	case 87:
	case 47: array2.setPoint(k,minX,minY);k++;break;
	case 39:
	case 79:
	case 89:
	case 69: array2.setPoint(k,maxX,minY);k++;break;
	case 71:
	case 31:
	case 41:
	case 21: array2.setPoint(k,minX,maxY);k++;break;
	case 93:
	case 13:
	case 63:
	case 23: array2.setPoint(k,maxX,maxY);k++;break;
	case 85: if (point.x()!=point_.x()) {array2.setPoint(k,point.x()-(long long)(point.x()-point_.x())*(point.y()-minY)/(point.y()-point_.y()),minY);k++;}
		 array2.setPoint(k,point);k++;break;
	case 25: if (point.x()!=point_.x()) {array2.setPoint(k,point.x()-(long long)(point.x()-point_.x())*(point.y()-maxY)/(point.y()-point_.y()),maxY);k++;}
		 array2.setPoint(k,point);k++;break;
	case 65: if (point.y()!=point_.y()) {array2.setPoint(k,maxX,point.y()-(long long)(point.y()-point_.y())*(point.x()-maxX)/(point.x()-point_.x()));k++;}
		 array2.setPoint(k,point);k++;break;
	case 45: if (point.y()!=point_.y()) {array2.setPoint(k,minX,point.y()-(long long)(point.y()-point_.y())*(point.x()-minX)/(point.x()-point_.x()));k++;}
		 array2.setPoint(k,point);k++;break;
	case 58: if (point.x()!=point_.x()) {array2.setPoint(k,point_.x()-(long long)(point.x()-point_.x())*(point_.y()-minY)/(point.y()-point_.y()),minY);k++;}
		array2.setPoint(k,point.x(),minY);k++;break;
	case 52: if (point.x()!=point_.x()) {array2.setPoint(k,point_.x()-(long long)(point.x()-point_.x())*(point_.y()-maxY)/(point.y()-point_.y()),maxY);k++;}
		array2.setPoint(k,point.x(),maxY);k++;break;
	case 56: if (point.y()!=point_.y()) {array2.setPoint(k,maxX,point_.y()+(long long)(point.y()-point_.y())*(maxX-point_.x())/(point.x()-point_.x()));k++;}
		array2.setPoint(k,maxX,point.y());k++;break;
	case 54: if (point.y()!=point_.y()) {array2.setPoint(k,minX,point_.y()+(long long)(point.y()-point_.y())*(minX-point_.x())/(point.x()-point_.x()));k++;}
		array2.setPoint(k,minX,point.y());k++;break;
	case 53: {QPoint h1=QPoint(maxX,point_.y()+(long long)(point.y()-point_.y())*(maxX-point_.x())/(point.x()-point_.x()));
		QPoint h2=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-maxY)/(point.y()-point_.y()),maxY);
		if (h1.y()<maxY){h2=h1;}
		array2.setPoint(k,h2);k++;}array2.setPoint(k,maxX,maxY);k++;break;
	case 35: {QPoint h1=QPoint(maxX,point.y()-(long long)(point.y()-point_.y())*(point.x()-maxX)/(point.x()-point_.x()));
		QPoint h2=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-maxY)/(point.y()-point_.y()),maxY);
		if (h1.y()<maxY){h2=h1;}
		array2.setPoint(k,h2);k++;}array2.setPoint(k,point);k++;break;
	case 59: {QPoint h1=QPoint(maxX,point_.y()+(long long)(point.y()-point_.y())*(maxX-point_.x())/(point.x()-point_.x()));
		QPoint h2=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-minY)/(point.y()-point_.y()),minY);
		if (h1.y()>minY){h2=h1;}
		array2.setPoint(k,h2);k++;}array2.setPoint(k,maxX,minY);k++;break;
	case 95: {QPoint h1=QPoint(maxX,point.y()-(long long)(point.y()-point_.y())*(point.x()-maxX)/(point.x()-point_.x()));
		QPoint h2=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-minY)/(point.y()-point_.y()),minY);
		if (h1.y()>minY){h2=h1;}
		array2.setPoint(k,h2);k++;}array2.setPoint(k,point);k++;break;
	case 57: {QPoint h1=QPoint(minX,point_.y()+(long long)(point.y()-point_.y())*(minX-point_.x())/(point.x()-point_.x()));
		QPoint h2=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-minY)/(point.y()-point_.y()),minY);
		if (h1.y()>minY){h2=h1;}
		array2.setPoint(k,h2);k++;}array2.setPoint(k,minX,minY);k++;break;
	case 75: {QPoint h1=QPoint(minX,point.y()-(long long)(point.y()-point_.y())*(point.x()-minX)/(point.x()-point_.x()));
		QPoint h2=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-minY)/(point.y()-point_.y()),minY);
		if (h1.y()>minY){h2=h1;}
		array2.setPoint(k,h2);k++;}array2.setPoint(k,point);k++;break;
	case 51: {QPoint h1=QPoint(minX,point_.y()+(long long)(point.y()-point_.y())*(minX-point_.x())/(point.x()-point_.x()));
		QPoint h2=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-maxY)/(point.y()-point_.y()),maxY);
		if (h1.y()<maxY){h2=h1;}
		array2.setPoint(k,h2);k++;}array2.setPoint(k,minX,maxY);k++;break;
	case 15: {QPoint h1=QPoint(minX,point.y()-(long long)(point.y()-point_.y())*(point.x()-minX)/(point.x()-point_.x()));
		QPoint h2=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-maxY)/(point.y()-point_.y()),maxY);
		if (h1.y()<maxY){h2=h1;}
		array2.setPoint(k,h2);k++;}array2.setPoint(k,point);k++;break;
	case 43: {QPoint h=QPoint(minX,point.y()-(long long)(point.y()-point_.y())*(point.x()-minX)/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,minX,maxY);k++;}
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 h=QPoint(maxX,point_.y()+(long long)(point.y()-point_.y())*(maxX-point_.x())/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 array2.setPoint(k,maxX,maxY);k++;
		 } break;
	case 83: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,maxX,minY);k++;}
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 h=QPoint(maxX,point_.y()+(long long)(point.y()-point_.y())*(maxX-point_.x())/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;};
		 array2.setPoint(k,maxX,maxY);k++;
		 } break;
	case 76: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 h=QPoint(minX,point.y()-(long long)(point.y()-point_.y())*(point.x()-minX)/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;};
		 h=QPoint(maxX,point_.y()+(long long)(point.y()-point_.y())*(maxX-point_.x())/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,maxX,minY);k++;}
		 array2.setPoint(k,maxX,point.y());k++; 
		 } break;
	case 73: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;}
		 else if (h.x()>maxX){array2.setPoint(k,maxX,minY);k++;}
		 h=QPoint(minX,point.y()-(long long)(point.y()-point_.y())*(point.x()-minX)/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;}
		 else if (h.x()<minX){array2.setPoint(k,minX,maxY);k++;}
		 h=QPoint(maxX,point_.y()+(long long)(point.y()-point_.y())*(maxX-point_.x())/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 array2.setPoint(k,maxX,maxY);k++;
		 } break;
	case 72: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 h=QPoint(minX,point.y()-(long long)(point.y()-point_.y())*(point.x()-minX)/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,minX,maxY);k++;}
		 array2.setPoint(k,point.x(),maxY);k++; 
		 } break;
	case 81: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,minX,minY);k++;}
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 h=QPoint(minX,point_.y()+(long long)(point.y()-point_.y())*(minX-point_.x())/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 array2.setPoint(k,minX,maxY);k++; 
		 } break;
	case 61: {QPoint h=QPoint(maxX,point.y()-(long long)(point.y()-point_.y())*(point.x()-maxX)/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,maxX,maxY);k++;}
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 h=QPoint(minX,point_.y()+(long long)(point.y()-point_.y())*(minX-point_.x())/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 array2.setPoint(k,minX,maxY);k++; 
		 } break;
	case 92: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 h=QPoint(maxX,point.y()-(long long)(point.y()-point_.y())*(point.x()-maxX)/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,maxX,maxY);k++;}
		 array2.setPoint(k,point.x(),maxY);k++; 
		 } break;
	case 91: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;}
		 else if (h.x()<minX){array2.setPoint(k,minX,minY);k++;}
		 h=QPoint(maxX,point.y()-(long long)(point.y()-point_.y())*(point.x()-maxX)/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;}
		 else if (h.x()>maxX) {array2.setPoint(k,maxX,maxY);k++;}
		 h=QPoint(minX,point_.y()+(long long)(point.y()-point_.y())*(minX-point_.x())/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 array2.setPoint(k,minX,maxY);k++; 
		 } break;
	case 94: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 h=QPoint(maxX,point.y()-(long long)(point.y()-point_.y())*(point.x()-maxX)/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 h=QPoint(minX,point_.y()+(long long)(point.y()-point_.y())*(minX-point_.x())/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,minX,minY);k++;}
		 array2.setPoint(k,minX,point.y());k++; 
		 } break;
	case 49: {QPoint h=QPoint(minX,point.y()-(long long)(point.y()-point_.y())*(point.x()-minX)/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,minX,minY);k++;}
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 h=QPoint(maxX,point_.y()+(long long)(point.y()-point_.y())*(maxX-point_.x())/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 array2.setPoint(k,maxX,minY);k++;
		 } break;
	case 29: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,maxX,maxY);k++;}
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 h=QPoint(maxX,point_.y()+(long long)(point.y()-point_.y())*(maxX-point_.x())/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 array2.setPoint(k,maxX,minY);k++;
		 } break;
	case 18: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 h=QPoint(minX,point.y()-(long long)(point.y()-point_.y())*(point.x()-minX)/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,minX,minY);k++;}
		 array2.setPoint(k,point.x(),minY);k++;
		 } break;
	case 19: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;}
		 else if (h.x()>maxX) {array2.setPoint(k,maxX,maxY);k++;}
		 h=QPoint(minX,point.y()-(long long)(point.y()-point_.y())*(point.x()-minX)/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;}
		 else if (h.x()<minX) {array2.setPoint(k,minX,minY);k++;}
		 h=QPoint(maxX,point_.y()+(long long)(point.y()-point_.y())*(maxX-point_.x())/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;};
		 array2.setPoint(k,maxX,minY);k++;
		 } break;
	case 16: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 h=QPoint(minX,point.y()-(long long)(point.y()-point_.y())*(point.x()-minX)/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 h=QPoint(maxX,point_.y()+(long long)(point.y()-point_.y())*(maxX-point_.x())/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,maxX,maxY);k++;}
		 array2.setPoint(k,maxX,point.y());k++; 
		 } break;
	case 27: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {
		 	array2.setPoint(k,h);k++;
		 	h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-minY)/(point.y()-point_.y()),minY); //top
		 	if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 	h=QPoint(minX,point_.y()+(long long)(point.y()-point_.y())*(minX-point_.x())/(point.x()-point_.x())); //left
		 	if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 } else {array2.setPoint(k,minX,maxY);k++;}
		 array2.setPoint(k,minX,minY);k++;
		 }break;
	case 67: {QPoint h=QPoint(maxX,point.y()-(long long)(point.y()-point_.y())*(point.x()-maxX)/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {
		  	array2.setPoint(k,h);k++;
		 	h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-minY)/(point.y()-point_.y()),minY); //top
		 	if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 	h=QPoint(minX,point_.y()+(long long)(point.y()-point_.y())*(minX-point_.x())/(point.x()-point_.x())); //left
		 	if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 } else {array2.setPoint(k,maxX,minY);k++;}
		 array2.setPoint(k,minX,minY);k++;
		 } break;
	case 34: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;}
		 h=QPoint(maxX,point.y()-(long long)(point.y()-point_.y())*(point.x()-maxX)/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 h=QPoint(minX,point_.y()+(long long)(point.y()-point_.y())*(minX-point_.x())/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;} 
		 else {array2.setPoint(k,minX,maxY);k++;}
		 array2.setPoint(k,minX,point.y());k++;
		 } break;
	case 37: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 h=QPoint(maxX,point.y()-(long long)(point.y()-point_.y())*(point.x()-maxX)/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;}
		 else if (h.x()>maxX) {array2.setPoint(k,maxX,minY);k++;};
		 h=QPoint(minX,point_.y()+(long long)(point.y()-point_.y())*(minX-point_.x())/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}
		 else if (h.y()>maxY) {array2.setPoint(k,minX,maxY);k++;};
		 array2.setPoint(k,minX,minY);k++;
		 } break;
	case 38: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;};
		 h=QPoint(maxX,point.y()-(long long)(point.y()-point_.y())*(point.x()-maxX)/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {array2.setPoint(k,h);k++;}; 
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,maxX,minY);k++;}
		 array2.setPoint(k,point.x(),minY);k++;
		 } break;
	case 48: {QPoint h=QPoint(minX,point.y()-(long long)(point.y()-point_.y())*(point.x()-minX)/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {
		 	array2.setPoint(k,h);k++;
		 	h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-minY)/(point.y()-point_.y()),minY); //top
		 	array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,minX,minY);k++;}
		 array2.setPoint(k,point.x(),minY);k++;
		 } break;
	case 46: {QPoint h=QPoint(minX,point.y()-(long long)(point.y()-point_.y())*(point.x()-minX)/(point.x()-point_.x())); //left
		 array2.setPoint(k,h);k++;
		 h=QPoint(maxX,point_.y()+(long long)(point.y()-point_.y())*(maxX-point_.x())/(point.x()-point_.x())); //right
		 array2.setPoint(k,h);k++;
		 array2.setPoint(k,maxX,point.y());k++; 
		 } break;
	case 42: {QPoint h=QPoint(minX,point.y()-(long long)(point.y()-point_.y())*(point.x()-minX)/(point.x()-point_.x())); //left
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {
		 	array2.setPoint(k,h);k++;
		 	h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 	array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,minX,maxY);k++;}
		 array2.setPoint(k,point.x(),maxY);k++;
		 } break;
	case 84: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {
		 	array2.setPoint(k,h);k++;
		 	h=QPoint(minX,point_.y()+(long long)(point.y()-point_.y())*(minX-point_.x())/(point.x()-point_.x())); //left
		 	array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,minX,minY);k++;}
		 array2.setPoint(k,minX,point.y());k++;
		 } break;
	case 82: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-minY)/(point.y()-point_.y()),minY); //top
		 array2.setPoint(k,h);k++;
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 array2.setPoint(k,h);k++;
		 array2.setPoint(k,point.x(),maxY);k++;
		 } break;
	case 86: {QPoint  h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-minY)/(point.y()-point_.y()),minY); //top
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {
		 	array2.setPoint(k,h);k++;
		 	h=QPoint(maxX,point_.y()+(long long)(point.y()-point_.y())*(maxX-point_.x())/(point.x()-point_.x())); //right
			array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,maxX,minY);k++;}
		 array2.setPoint(k,maxX,point.y());k++;
		 } break;
	case 68: {QPoint h=QPoint(maxX,point.y()-(long long)(point.y()-point_.y())*(point.x()-maxX)/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {
		 	array2.setPoint(k,h);k++; 
		 	h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-minY)/(point.y()-point_.y()),minY); //top
			array2.setPoint(k,h);k++;}
		 else {array2.setPoint(k,maxX,minY);k++;}
		 array2.setPoint(k,point.x(),minY);k++;
		 } break;
	case 64: {QPoint h=QPoint(maxX,point.y()-(long long)(point.y()-point_.y())*(point.x()-maxX)/(point.x()-point_.x())); //right
		 array2.setPoint(k,h);k++;
		 h=QPoint(minX,point_.y()+(long long)(point.y()-point_.y())*(minX-point_.x())/(point.x()-point_.x())); //left
		 array2.setPoint(k,h);k++;
		 array2.setPoint(k,minX,point.y());k++;
		 } break;
	case 62: {QPoint  h=QPoint(maxX,point.y()-(long long)(point.y()-point_.y())*(point.x()-maxX)/(point.x()-point_.x())); //right
		 if ((h.y()>=minY)&&(h.y()<=maxY)) {
		 	array2.setPoint(k,h);k++;
		 	h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
			array2.setPoint(k,h);k++;}
		 else  {array2.setPoint(k,maxX,maxY);k++;};
		 array2.setPoint(k,point.x(),maxY);k++;
		 } break;
	case 24: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {
		 	array2.setPoint(k,h);k++;
		 	h=QPoint(minX,point_.y()+(long long)(point.y()-point_.y())*(minX-point_.x())/(point.x()-point_.x())); //left
		        array2.setPoint(k,h);k++;}
		 else  {array2.setPoint(k,minX,maxY);k++;};
		 array2.setPoint(k,minX,point.y());k++;
		 } break;
	case 28: {QPoint h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 array2.setPoint(k,h);k++;
		 h=QPoint(point_.x()-(long long)(point.x()-point_.x())*(point_.y()-minY)/(point.y()-point_.y()),minY); //top
		 array2.setPoint(k,h);k++;
		 array2.setPoint(k,point.x(),minY);k++;
		 } break;
	case 26: {QPoint  h=QPoint(point.x()-(long long)(point.x()-point_.x())*(point.y()-maxY)/(point.y()-point_.y()),maxY); //bottom
		 if ((h.x()>=minX)&&(h.x()<=maxX)) {
		 	array2.setPoint(k,h);k++;
		 	h=QPoint(maxX,point_.y()+(long long)(point.y()-point_.y())*(maxX-point_.x())/(point.x()-point_.x())); //right
		 	array2.setPoint(k,h);k++; } 
		 else {array2.setPoint(k,maxX,maxY);k++;};
		 array2.setPoint(k,maxX,point.y());k++;
		 } break;
	default: 
           point_=point;
	   if (point.y()>=maxY){point_.setY(maxY);}
	   else if (point.y()<=minY){point_.setY(minY);}
	   if (point.x()>=maxX){point_.setX(maxX);}
           else if (point.x()<=minX){point_.setX(minX);}
	   array2.setPoint(k,point_);k++;
	  // printf("missing %d\n",(a*10+b));
	   break;
	}
	point_=point;
	a=b;
	}
array2.resize(k);
return array2;
}

QPoint element::convert(const QPoint point_,const strans trans){
QPoint point=trans.mapDraw(point_);
if (point.x()>(1<<15)-5){point.setX((1<<15)-5);}
if (point.x()<-(1<<15)+5){point.setX(-(1<<15)+5);}
if (point.y()>(1<<15)-5){point.setY((1<<15)-5);}
if (point.y()<-(1<<15)+5){point.setY(-(1<<15)+5);}
return point;
}



pointArray element::convert(const QRect rect,const strans trans){
  pointArray array;
  array.resize(5);
  array.setPoint(0,rect.left(),rect.top());
  array.setPoint(1,rect.right(),rect.top());
  array.setPoint(2,rect.right(),rect.bottom());
  array.setPoint(3,rect.left(),rect.bottom());
  array.setPoint(4,rect.left(),rect.top());
  return convert(array,trans);
}

cell* element::depend(){
return NULL;
}

bool element::cutPoint3(QPoint p1,QPoint p2,QPoint p3,QPoint p4,QPoint *pc){
// independent of p1,p2,p3,p4
double m1,m2,b1,b2;
QPoint dif1,dif2;
dif1=p2-p1;
dif2=p4-p3;
pc->setX(INT_MAX);
pc->setY(INT_MAX);
//printf("cp3\n");
if ((dif1.x()!=0)&&(dif2.x()!=0)){
	//printf("if1\n");
	m1=(double)(dif1.y())/(double)(dif1.x());
	m2=(double)(dif2.y())/(double)(dif2.x());
	b1=-m1*(double)p1.x()+p1.y();
	b2=-m2*(double)p3.x()+p3.y();
	if (m1==m2){return false;}
	pc->setX(runden((b2-b1)/(m1-m2)));
	if (dif1.y()==0){pc->setY(p1.y());}
	else if (dif2.y()==0) {pc->setY(p3.y());}
	else if (abs((int)m1)<abs((int)m2)) {pc->setY(runden(m1*(double)pc->x()+b1));}
	else {pc->setY(runden(m2*(double)pc->x()+b2));}
	//printf("m %f %f x %d y %d b %f %f\n",m1,m2,pc->x(),pc->y(),b1,b2);
	}
else if ((dif1.x()==0)&&(dif2.x()!=0)){
	//printf("if2\n");
	m2=(double)(dif2.y())/(double)(dif2.x());
	b2=-m2*(double)p3.x()+p3.y();
	pc->setX(p1.x());
	pc->setY(runden(m2*(double)pc->x()+b2));
	if (dif1.y()==0) return false;
	if (dif2.y()==0) pc->setY(p3.y());}
else if ((dif1.x()!=0)&&(dif2.x()==0)){
	//printf("if3 %d %d\n",dif1.x(),dif2.x());
	m1=(double)(dif1.y())/(double)(dif1.x());
	b1=-m1*(double)p1.x()+p1.y();
	pc->setX(p3.x());
	pc->setY(runden(m1*(double)pc->x()+b1));
	if (dif2.y()==0) return false;
	if (dif1.y()==0) pc->setY(p1.y());}
else if ((dif1.x()==0)&&(dif2.x()==0)){return false;}
//printf("ifend\n");
return true;
}
bool element::cutPoint(QPoint p1,QPoint p2,QPoint p3,QPoint p4,QPoint *pc){
//between or on p1-p2+p3-p4
int help;
if (!element::cutPoint3(p1,p2,p3,p4,pc)) return false;
/*printf("cutPoint\n");
printf("p1: x: %d y: %d\n",p1.x(),p1.y());
printf("p2: x: %d y: %d\n",p2.x(),p2.y());
printf("p3: x: %d y: %d\n",p3.x(),p3.y());
printf("p4: x: %d y: %d\n",p4.x(),p4.y());
printf("pc: x: %d y: %d\n",pc->x(),pc->y());*/
if (p1.x()>p2.x()){help=p1.x();p1.setX(p2.x());p2.setX(help);}
if (p3.x()>p4.x()){help=p3.x();p3.setX(p4.x());p4.setX(help);}
if (pc->x()<p1.x()){return false;}
if (pc->x()>p2.x()){return false;}
if (pc->x()<p3.x()){return false;}
if (pc->x()>p4.x()){return false;}
if (p1.y()>p2.y()){help=p1.y();p1.setY(p2.y());p2.setY(help);}
if (p3.y()>p4.y()){help=p3.y();p3.setY(p4.y());p4.setY(help);}
if (pc->y()<p1.y()){return false;}
if (pc->y()>p2.y()){return false;}
if (pc->y()<p3.y()){return false;}
if (pc->y()>p4.y()){return false;}
//printf("found\n");
return true;
}

bool element::cutPoint4(QPoint p1,QPoint p2,QPoint p3,QPoint p4,QPoint *pc){
//between or on p1-p2+p3-p4 +1
int help;
if (!element::cutPoint3(p1,p2,p3,p4,pc)) return false;
/*printf("cutPoint\n");
printf("p1: x: %d y: %d\n",p1.x(),p1.y());
printf("p2: x: %d y: %d\n",p2.x(),p2.y());
printf("p3: x: %d y: %d\n",p3.x(),p3.y());
printf("p4: x: %d y: %d\n",p4.x(),p4.y());
printf("pc: x: %d y: %d\n",pc->x(),pc->y());*/
if (p1.x()>p2.x()){help=p1.x();p1.setX(p2.x());p2.setX(help);}
if (p3.x()>p4.x()){help=p3.x();p3.setX(p4.x());p4.setX(help);}
if (pc->x()<p1.x()-1){return false;}
if (pc->x()>p2.x()+1){return false;}
if (pc->x()<p3.x()-1){return false;}
if (pc->x()>p4.x()*1){return false;}
if (p1.y()>p2.y()){help=p1.y();p1.setY(p2.y());p2.setY(help);}
if (p3.y()>p4.y()){help=p3.y();p3.setY(p4.y());p4.setY(help);}
if (pc->y()<p1.y()-1){return false;}
if (pc->y()>p2.y()+1){return false;}
if (pc->y()<p3.y()-1){return false;}
if (pc->y()>p4.y()+1){return false;}
//printf("found\n");
return true;
}

bool element::cutPoint2(QPoint p1,QPoint p2,QPoint p3,QPoint p4,QPoint *pc){
//between  p1-p2+p3-p4
int help;
if (!cutPoint3(p1,p2,p3,p4,pc)) return false;
if (*pc==p1){return false;}
if (*pc==p2){return false;}
if (*pc==p3){return false;}
if (*pc==p4){return false;}
if (p1.x()>p2.x()){help=p1.x();p1.setX(p2.x());p2.setX(help);}
if (p3.x()>p4.x()){help=p3.x();p3.setX(p4.x());p4.setX(help);}
if (pc->x()<p1.x()){return false;}
if (pc->x()>p2.x()){return false;}
if (pc->x()<p3.x()){return false;}
if (pc->x()>p4.x()){return false;}
if (p1.y()>p2.y()){help=p1.y();p1.setY(p2.y());p2.setY(help);}
if (p3.y()>p4.y()){help=p3.y();p3.setY(p4.y());p4.setY(help);}
if (pc->y()<p1.y()){return false;}
if (pc->y()>p2.y()){return false;}
if (pc->y()<p3.y()){return false;}
if (pc->y()>p4.y()){return false;}
return true;
}

bool element::cutting(QPoint p1,QPoint p2,QPoint p3,QPoint p4){
	int max2=p3.x();
	int min2=p4.x();
	if (p3.x()<p4.x()) {
		max2=p4.x();
		min2=p3.x();
	}
	int max1=p1.x();
	int min1=p2.x();
	if (p1.x()<p2.x()) {
		max1=p2.x();
		min1=p1.x();
	}
	if (max1<min2) return false;
	if (max2<min1) return false;
	max2=p3.y();
	min2=p4.y();
	if (p3.y()<p4.y()) {
		max2=p4.y();
		min2=p3.y();
	}
	max1=p1.y();
	min1=p2.y();
	if (p1.y()<p2.y()) {
		max1=p2.y();
		min1=p1.y();
	}
	if (max1<min2) return false;
	if (max2<min1) return false;
	QPoint p;
	if (cutPoint(p1,p2,p3,p4,&p))return true;
	if (identical(p1,p2,p3,p4))return true;
	return false;
}

bool element::identical(QPoint p1,QPoint p2,QPoint p3,QPoint p4){
double m1,m2,b1,b2;
QPoint dif1,dif2;
dif1=p2-p1;
dif2=p4-p3;
if ((dif1.y()!=0)&&(dif2.y()!=0)){
	m1=(double)(dif1.x())/(double)(dif1.y());
	m2=(double)(dif2.x())/(double)(dif2.y());
	//printf("m %f %f\n",m1,m2);
	if (m1!=m2){return false;}
	b1=-m1*(double)p1.y()+p1.x();
	b2=-m2*(double)p3.y()+p3.x();
	//printf("b %f %f\n",b1,b2);
	if (b1!=b2){return false;}
	return true;}
else if ((dif1.x()!=0)&&(dif2.x()!=0)){
	m1=(double)(dif1.y())/(double)(dif1.x());
	m2=(double)(dif2.y())/(double)(dif2.x());
	//printf("m %f %f\n",m1,m2);
	if (m1!=m2){return false;}
	b1=-m1*(double)p1.x()+p1.y();
	b2=-m2*(double)p3.x()+p3.y();
	//printf("b %f %f\n",b1,b2);
	if (b1!=b2){return false;}
	return true;}
return false;
}

bool element::parallel(QPoint p1,QPoint p2,QPoint p3,QPoint p4){
double m1,m2;
QPoint dif1,dif2;
dif1=p2-p1;
dif2=p4-p3;
if ((dif1.y()!=0)&&(dif2.y()!=0)){
	m1=(double)(dif1.x())/(double)(dif1.y());
	m2=(double)(dif2.x())/(double)(dif2.y());
	if (m1!=m2){return false;}
	return true;}
else if ((dif1.x()!=0)&&(dif2.x()!=0)){
	m1=(double)(dif1.y())/(double)(dif1.x());
	m2=(double)(dif2.y())/(double)(dif2.x());
	if (m1!=m2){return false;}
	return true;}
return false;
}

bool element::nearlyParallel(QPoint p1,QPoint p2,QPoint p3,QPoint p4){
double m1,m2;
QPoint dif1,dif2;
dif1=p2-p1;
dif2=p4-p3;
if ((dif1.y()!=0)&&(dif2.y()!=0)){
	m1=(double)(dif1.x())/(double)(dif1.y());
	m2=(double)(dif2.x())/(double)(dif2.y());
	m2=m2-m1;
	if ((m2<0)&&(-0.005>m2)){return false;}
	if ((m2>0)&&(0.005<m2)){return false;}
	return true;}
else if ((dif1.x()!=0)&&(dif2.x()!=0)){
	m1=(double)(dif1.y())/(double)(dif1.x());
	m2=(double)(dif2.y())/(double)(dif2.x());
	m2=m2-m1;
	if ((m2<0)&&(-0.005>m2)){return false;}
	if ((m2>0)&&(0.005<m2)){return false;}
	return true;}
return false;
}

bool element::onLine2(QPoint p1,QPoint p2, QPoint p3){
double m1,b1;
QPoint dif1;
int help;
dif1=p2-p1;
if ((dif1.x()!=0)){
	m1=(double)(dif1.y())/(double)(dif1.x());
	b1=-m1*(double)p1.x()+p1.y();
	if (p3.y()!=m1*(double)(p3.x())+b1){return false;}}
else {
	if (p3.x()!=p1.x()){return false;}}
if (p3==p1){return false;}
if (p3==p2){return false;}
if (p1.x()>p2.x()){help=p1.x();p1.setX(p2.x());p2.setX(help);}
if (p1.y()>p2.y()){help=p1.y();p1.setY(p2.y());p2.setY(help);}
if (p3.x()<p1.x()){return false;}
if (p3.y()<p1.y()){return false;}
if (p3.x()>p2.x()){return false;}
if (p3.y()>p2.y()){return false;}

return true;
}
bool element::onLine(QPoint p1,QPoint p2, QPoint p3){
// true if p3 on line p1-p2
double m1,b1;
QPoint dif1;
int help;
dif1=p2-p1;
if ((dif1.x()!=0)){
	m1=(double)(dif1.y())/(double)(dif1.x());
	b1=-m1*(double)p1.x()+p1.y();
	if (p3.y()!=m1*(double)(p3.x())+b1){return false;}}
else {
	if (p3.x()!=p1.x()){return false;}}
if (p1.x()>p2.x()){help=p1.x();p1.setX(p2.x());p2.setX(help);}
if (p1.y()>p2.y()){help=p1.y();p1.setY(p2.y());p2.setY(help);}
if (p3.x()<p1.x()){return false;}
if (p3.y()<p1.y()){return false;}
if (p3.x()>p2.x()){return false;}
if (p3.y()>p2.y()){return false;}
return true;
}
bool element::nearLine(QPoint p1,QPoint p2, QPoint p3){
double m1,b1;
QPoint dif1;
int help;
dif1=p2-p1;
if ((dif1.x()!=0)){
	m1=(double)(dif1.y())/(double)(dif1.x());
	b1=-m1*(double)p1.x()+p1.y();
	if (5<abs((int)(m1*(double)(p3.x())+b1-p3.y()))){return false;}}
else {
	if (5<abs(p1.x()-p3.x())){return false;}}
if (p1.x()>p2.x()){help=p1.x();p1.setX(p2.x());p2.setX(help);}
if (p1.y()>p2.y()){help=p1.y();p1.setY(p2.y());p2.setY(help);}
if (p3.x()<p1.x()-2){return false;}
if (p3.y()<p1.y()-2){return false;}
if (p3.x()>p2.x()+2){return false;}
if (p3.y()>p2.y()+2){return false;}
return true;
}
double element::angle(QPoint p1,QPoint p2, QPoint p3){
double a1=0,a2=0;
/*printf("angle\n");
printf("p1: x: %d y: %d\n",p1.x(),p1.y());
printf("p2: x: %d y: %d\n",p2.x(),p2.y());
printf("p3: x: %d y: %d\n",p3.x(),p3.y());*/
QPoint dif1,dif2;
dif1=p2-p1;
dif2=p3-p2;
/*printf("dif1: x: %d y: %d\n",dif1.x(),dif1.y());
printf("dif2: x: %d y: %d\n",dif2.x(),dif2.y());*/
if (dif1.x()!=0) {a1=atan((double)(dif1.y())/(double)(dif1.x()))/2/M_PI*360;
		if (dif1.x()<0){a1-=180;}
		if (a1<-180){a1+=360;}}
else {if (dif1.y()>0){a1=90;}else {a1=-90;}}
if (dif2.x()!=0) {a2=atan((double)(dif2.y())/(double)(dif2.x()))/2/M_PI*360;
		if (dif2.x()<0){a2-=180;}
		if (a2<-180){a2+=360;}}
else {if (dif2.y()>0){a2=90;}else {a2=-90;}}
//printf("a1 %f a2 %f\n",a1,a2);
a1=a2-a1;
if (a1<=-180) a1+=360;
if (a1>=180) a1-=360;
return (a1);
}
double element::angle(QPoint p1,QPoint p2){
double a1=0;
QPoint dif1;
dif1=p2-p1;
if (dif1.x()!=0) {a1=atan((double)(dif1.y())/(double)(dif1.x()))/2/M_PI*360;
		if (dif1.x()<0){a1-=180;}
		if (a1<-180){a1+=360;}}
else {if (dif1.y()>0){a1=90;}else {a1=-90;}}
if (a1<=-180) a1+=360;
if (a1>180) a1-=360;
return (a1);
}

double element::distance(QPoint p1,QPoint p2, QPoint p3){
// >0 if left off line
double m1,b1,wert;
QPoint dif1;
dif1=p2-p1;
if ((dif1.x()!=0)){
	m1=(double)(dif1.y())/(double)(dif1.x());
	b1=-m1*(double)p1.x()+p1.y();
	wert=m1*(double)(p3.x())+b1-(double)p3.y();
	if (dif1.y()==0) {if (dif1.x()>0){return -wert;}
			else return wert;}
	if (dif1.x()>0) {return -wert;}
	if (dif1.x()<0) {return +wert;}
	else return wert;}
else {	if (dif1.y()>0){ return (double)(p1.x()-p3.x());}
	else return (double)(p3.x()-p1.x());}
return 0;
}

double element::distance(QPoint p1,QPoint p2){
  double dx=p1.x()-p2.x();
  double dy=p1.y()-p2.y();
  return sqrt(dx*dx+dy*dy); 
}
double element::length(QPoint p){
  return sqrt((double)p.x()*(double)p.x()+(double)p.y()*(double)p.y()); 
}

bool element::pointInPolygon(pointArray array, QPoint point){
//QPoint p=QPoint(-1<<30,-1<<30);
QPoint p;
QPoint p2;
p=array.point(0);
p2=p;
for (int i=0; i<array.size()-1;i++){
  if (p.x()>array.point(i).x())p.setX(array.point(i).x()); 
  if (p2.x()<array.point(i).x())p2.setX(array.point(i).x()); 
  if (p.y()>array.point(i).y())p.setY(array.point(i).y()); 
  if (p2.y()<array.point(i).y())p2.setY(array.point(i).y()); 
};
//printf("test. %d %d : max %d %d : min %d %d\n",point.x(),point.y(),p.x(),p.y(),p2.x(),p2.y());
if (point.x()<p.x()) return false;
if (point.x()>p2.x()) return false;
if (point.y()<p.y()) return false;
if (point.y()>p2.y()) return false;
p-=QPoint(107,97);
QPoint q;
//printf("x %d   y %d  ",point.x(),point.y());
//printf("p x%d  y %d\n",p.x(),p.y());
int anz=0;
int it=0;
for (int i=0; i<array.size()-1;i++){
   while (identical(point,p,array.point(i),array.point(i+1))){p.setX(p.x()-43);p.setY(p.y()-3);i=0;anz=0;}
   if (cutPoint4(point,p,array.point(i),array.point(i+1),&q)){
	if ((abs(q.x()-array.point(i).x())+abs(q.y()-array.point(i).y())<3)|| (abs(q.x()-array.point(i+1).x())+abs(q.y()-array.point(i+1).y())<3)){
		if (point==array.point(i))return true;
		//printf("%d %d %d %d %d %d %d %d %d\n",it,p.x(),p.y(),q.x(),q.y(), array.point(i).x(),array.point(i).y(),array.point(i+1).x(),array.point(i+1).y());
		p-=QPoint(13,19);
		i=-1;anz=0;it++;
		if (it<2) p-=QPoint(13,19);
		else if (it<3) p-=QPoint(0,217);
		else if (it<4) p-=QPoint(287,5217);
		else if (it>10) return false;
		}
	else if (q!=array.point(i+1))
   	 //if (!onLine(p,point,array.point(i+1)))
	{anz++;
	//printf("++%d  i:%d\n",anz,i);
	//printf(" line x %d   y %d\n",array.point(i+1).x(),array.point(i+1).y());
	//printf(" cp x %d   y %d\n",q.x(),q.y());
	}
   	}
}
anz=anz%2;
if (anz==1) return true;
return false;
}

bool element::pointOnPolygon(pointArray array, QPoint point){
  bool b=false;
  for (int i=0; i<array.size()-1;i++){
   	if (onLine(array.point(i),array.point(i+1),point)){b=true;}
   	}
  return b;
}

int element::runden(double d){
  if (d>0) {return (int)(d+0.5);}
  else  {return (int)(d-0.5);}
}

QPoint element::round(QPoint point, int i){
  QPoint p;
  if (i>1){
  if (point.x()>0) {p.setX(((point.x()+(i/2))/i)*i);}
  else {p.setX(((point.x()-(i/2))/i)*i);}
  if (point.y()>0) {p.setY(((point.y()+(i/2))/i)*i);}
  else {p.setY(((point.y()-(i/2))/i)*i);}}
  return p;
}

pointArray element::spirale(QPoint center,QPoint p1, QPoint p2,double anglestep){
pointArray array;
array.resize(1);
array.setPoint(0,p1);
double a1=angle(center,p1);
double a2=angle(center,p2);
double dist1=distance(center,p1);
double dist2=distance(center,p2);
double dist;
int i=1;
if (a2<=a1) {a2+=360;}
for (double ang=a1+anglestep;ang<a2;ang+=anglestep){
	array.resize(i+1);
	dist=dist1+(ang-a1)*(dist2-dist1)/(a2-a1);
	array.setPoint(i,center.x()+runden(dist*cos(ang/180*M_PI)),center.y()+runden(dist*sin(ang/180*M_PI)));
	i++;}
array.resize(i+1);
array.setPoint(i,p2);
return array;
}

pointArray element::ellipse(QPoint center,int rx,int ry,double anglestep){
pointArray array;
array.resize(0);
int i=0;
//array.setPoint(0,center+QPoint(0,ry));
for (double ang=0;ang<360;ang+=anglestep){
	array.resize(i+1);
	array.setPoint(i,center.x()+runden(rx*cos(ang/180*M_PI)),center.y()+runden(ry*sin(ang/180*M_PI)));
	i++;}
array.resize(i+1);
array.setPoint(i,array.point(0));
return array;
}

void element::setWidth(int ){}
void element::setCap(int ){}
void element::saveOASIS( oasis *){}

void element::bezier3(                            // Zeichne Bezierkurve 3. Grades
    double px0, double py0,    // anhand des Stuetzpunktes p0
    double px1, double py1,    // anhand des Stuetzpunktes p1
    double px2, double py2,    // anhand des Stuetzpunktes p2
    double px3, double py3,    // anhand des Stuetzpunktes p3
    int depth,                 // aktuelle Rekursionstiefe
    pointArray *a,		//punktarray
    int maxDepth)
{
    double qx01,qy01,qx12,qy12,qx23,qy23,qx012,qy012,qx123,qy123,qx0123,qy0123;
    if (depth > maxDepth)   {                    // Iterationstiefe erreicht
        a->resize(a->size()+1);
        a->setPoint(a->size()-1,(int)px0,(int)py0);
    } else {
        depth++;
        qx01   = (px0+px1)/2;
        qy01   = (py0+py1)/2;
        qx12   = (px1+px2)/2;
        qy12   = (py1+py2)/2;
        qx23   = (px2+px3)/2;
        qy23   = (py2+py3)/2;
        qx012  = (qx01+qx12)/2;
        qy012  = (qy01+qy12)/2;
        qx123  = (qx12+qx23)/2;
        qy123  = (qy12+qy23)/2;
        qx0123 = (qx012+qx123)/2;
        qy0123 = (qy012+qy123)/2;
        bezier3 (px0,py0,qx01,qy01,qx012,qy012,qx0123,qy0123,depth,a,maxDepth);
        bezier3 (qx0123,qy0123,qx123,qy123,qx23,qy23,px3,py3,depth,a,maxDepth);
    }
}
pointArray element::bezier3(QPoint pstart, QPoint pend, QPoint pbezierstart, QPoint pbezierend, int maxDepth){
  if (maxDepth==-2) maxDepth=setup::defaultBezierIteration;
 pointArray a;
  a.resize(0);
  bezier3(pstart.x(),pstart.y(),pbezierstart.x(),pbezierstart.y(),pbezierend.x(),pbezierend.y(),pend.x(),pend.y(),0,&a,maxDepth);
  a.resize(a.size()+1);
  a.setPoint(a.size()-1,pend);
  return a;
}
pointArray element::bezier2(QPoint pstart, QPoint pend, QPoint pbezier, int maxDepth){
  if (maxDepth==-2) maxDepth=setup::defaultBezierIteration;
  pointArray a;
  a.resize(0);
  bezier2(pstart.x(),pstart.y(),pbezier.x(),pbezier.y(),pend.x(),pend.y(),0,&a,maxDepth);
  a.resize(a.size()+1);
  a.setPoint(a.size()-1,pend);
  return a;
}

void element::bezier2(                            // Zeichne Bezierkurve 2. Grades
    double px0, double py0,    // anhand des Stuetzpunktes p0
    double px1, double py1,    // anhand des Stuetzpunktes p1
    double px2, double py2,    // anhand des Stuetzpunktes p2
    int depth,                 // aktuelle Rekursionstiefe
    pointArray *a,	       //punktarray
    int maxDepth)		
{
    double qx01,qy01,qx12,qy12,qx012,qy012;

    if (depth > maxDepth)   {                    // Iterationstiefe erreicht
        a->resize(a->size()+1);
        a->setPoint(a->size()-1,(int)px0,(int)py0);
    } else {
        depth++;
        qx01   = (px0+px1)/2;
        qy01   = (py0+py1)/2;
        qx12   = (px1+px2)/2;
        qy12   = (py1+py2)/2;
        qx012  = (qx01+qx12)/2;
        qy012  = (qy01+qy12)/2;
        bezier2 (px0,py0,qx01,qy01,qx012,qy012,depth,a,maxDepth);
        bezier2 (qx012,qy012,qx12,qy12,px2,py2,depth,a,maxDepth);
    }
}

pointArray element::fitToCircle(pointArray pointarray, bool useLastPoint){
// Kreis anfitten an x[i], y[i], i=0...(n-1)
if (pointarray.size()<=1) return pointArray(0);
if (pointarray.size()==2) {
	QPoint pc=(pointarray.point(0)+pointarray.point(1))/2;
	pointArray a=element::spirale(pc,pointarray.point(0),pointarray.point(0),setup::circularDefault);
	return a;
	}
QVector<double> x(pointarray.size()),y(pointarray.size());
QVector<double> c(pointarray.size()),e(pointarray.size());
if (!useLastPoint) {
	x.resize(pointarray.size()-1);
	y.resize(pointarray.size()-1);
	c.resize(pointarray.size()-1);
	e.resize(pointarray.size()-1);
	}
for (int i=0; i<x.size(); i++) {
	x[i]=pointarray.point(i).x();
	y[i]=pointarray.point(i).y();
	}

double a1,a2,a3,b1,b2,b3;
double a11,a12,a13,a21,a22,a23,a31,a32,a33;
double l11,l21,l22,l31,l32,l33,u12,u13,u23,y1,y2,y3;
double xc,yc,radius;

// Belegen der Hilfsarrays
for (int i=0; i<x.size(); i++) {
	c[i] = x[i]*x[i] + y[i]*y[i];
	e[i] = 1;
}

a11 = dotProduct(x,x);
a12 = dotProduct(x,y);
a13 = dotProduct(x,e);
a21 = dotProduct(x,y);
a22 = dotProduct(y,y);
a23 = dotProduct(y,e);
a31 = dotProduct(x,e);
a32 = dotProduct(y,e);
a33 = dotProduct(e,e);

b1 = dotProduct(x,c);
b2 = dotProduct(y,c);
b3 = dotProduct(e,c);

// L-U-Decomposition
l11 = a11;
l21 = a21;
l31 = a31;
if (l11==0) return pointArray(0);
u12 = a12/l11;
u13 = a13/l11;
l22 = a22 - l21*u12;
if (l22==0) return pointArray(0);
l32 = a32 - l31*u12;
u23 = (a23 - l21*u13)/l22;
l33 = a33 - l31*u13 - l32*u23;
if (l33==0) return pointArray(0);
// Solve Step 1:
y1 = b1/l11;
y2 = (b2 - y1*l21)/l22;
y3 = (b3 - y1*l31 - y2*l32)/l33;

// Solve Step 2:
a3 = y3;
a2 = y2 - u23*a3;
a1 = y1 - u13*a3 - u12*a2;

xc = a1/2;
yc = a2/2;
radius =element::runden( sqrt((a1*a1+a2*a2)/4+a3));
int r=element::runden(radius);
QPoint center=QPoint(runden(xc),runden(yc));

pointArray points=spirale(center,center+QPoint(r,0),center+QPoint(r,0),setup::circularDefault);
return points;
}

double element::dotProduct( QVector<double> x, QVector<double> y) {
   int i;
   double sum;
   sum = 0;
   for (i=0; i<x.size(); i++) {
	sum += x[i] * y[i];
   };
   return sum;
}

element * element::copy(){
	element *e;
	if (isBox()) e=new box(getBox());
	else if (isPath()) e=new path(getPath());
	else if (isPolygon())e=new polygon(getPolygon());
	else if (isCellref()) e=new cellref(getCellref());
	else if (isCellrefArray())e=new cellrefArray(getCellrefArray());
	else if (isText())e=new txt(getText());
	else e=new element();
	return e;
}

QList<int> element::getNodes(int node){
	QList<int>n;
	for (int i=0;i<property.size();i++)
	if (property.at(i).isNum()){
		int pnum=property.at(i).getNum();
		if (pnum==node+100000){
			n<<property.at(i).getValueInt();
	}
	}
	return n;
}


void element::connectNodes(int node1 ,int node2){
	property<<propertyItem(100000+node1,node2);
}


void element::setNode(int node){
	for (int i=0;i<property.size();i++)
	if (property.at(i).isNum()){
		int pnum=property.at(i).getNum();
		if (pnum==100000){
			property[i].setValue((int)(node));
			return;
	}
	}
	property<<propertyItem(100000,node);
}

void element::clearNode(){
	for (int i=0;i<property.size();i++)
	if (property.at(i).isNum()){
		int pnum=property.at(i).getNum();
		if (pnum>=100000){
			property.removeAt(i);
			i--;
	}
  }
}

int element::getNode(){
//printf("size%d\n",property.size());
	for (int i=0;i<property.size();i++)
	if (property.at(i).isNum()){
		int pnum=property.at(i).getNum();
		if (pnum==100000){
			return property.at(i).getValueInt();
	}
	}
return -1;
}

void element::setDeviceName(QString name){
	for (int i=0;i<property.size();i++)
		{
		int pnum=property.at(i).getNum();
		if (pnum==10){
			property[i].setValue(name);
			return;
	}
	}
	property<<propertyItem(10,name);
}

QString element::getDeviceName(){
for (int i=0;i<property.size();i++)
		{
		int pnum=property.at(i).getNum();
		if (pnum==10){
			return property.at(i).getValueString();
	}
	}
return QString("");
}

void element::paintHighlightedBackground(QPainter *po,strans trans_ ){
 QColor c=setup::highlightColor;
 c.setAlpha(60);
 po->setPen(c);
 QBrush br=QBrush(Qt::SolidPattern);
  c.setAlpha(45);
  br.setColor(c);
  po->setBrush(br);
  QPoint paintMax=QPoint(INT_MIN,INT_MIN);
  QPoint paintMin=QPoint(INT_MAX,INT_MAX);	
 uint i=0;
  paintInfo(&paintMin,&paintMax,&i);
  paintMin=convert(paintMin,trans_);
  paintMax=convert(paintMax,trans_);
  po->drawRect(paintMin.x(),paintMin.y(),paintMax.x()-paintMin.x(),paintMax.y()-paintMin.y());
}
