/***************************************************************************
 *   Copyright (C) 2005 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 DRC_H
#define DRC_H

#include <qobject.h>
#include <qstring.h>
#include "drawingfield.h"
class drawingField;
class booleanHandler;
class layout;
/**
@author Juergen Thies
*/
//! Design Rule Checker
/*!
  This class allows the access to the design rule checker. For each rule available in the graphical user interface, there is a corresponding method in this class. Please see @link "Design Rule Checker" documentaion for a more dailed description of the checks.<br>

For a complete DRC a plenty of rules are required. For a complete DRC in one step please create a macro with all your rules. There you can also give each rule an individual name. This macro gives an example. It is also included in the example macros.<br><br>@code
#!/usr/bin/layout<br>
#name=Macro: drc example.layout<br>
#help=example for a drc macro<br>
<br>
<br>
int main(){<br>
<br>
layout->drcTool->result="DRC (LayoutEditor example) \r\n";<br>
<br>
// setup error layer<br>
layout->drawing->activeLayer=0;<br>
layout->drcTool->setErrorLayerToActiveLayer();<br>
<br>
// check for layer metal 1<br>
layout->drcTool->ruleName= "Minimum Size Metal1";<br>
layout->drcTool->minimumSize(800,6,true);<br>
layout->drcTool->ruleName= "Minimum Distance Metal1";<br>
layout->drcTool->minimumElementDistance(800,6,true);<br>
<br>
// check for layer metal 2<br>
layout->drcTool->ruleName= "Minimum Size Metal2";<br>
layout->drcTool->minimumSize(900,8,true);<br>
layout->drcTool->ruleName= "Minimum Distance Metal2";<br>
layout->drcTool->minimumElementDistance(900,8,true);<br>
<br>
// check for via1  (metal1 to metal2)<br>
layout->drcTool->ruleName= "Via in metal1";<br>
layout->drcTool->inside(50,7,6);<br>
layout->drcTool->ruleName= "Via in metal2";<br>
layout->drcTool->inside(60,7,8);<br>
<br>
<br>
layout->drcTool->showReport();<br>
<br>
}@endcode
*/
class drc : public QObject
{
Q_OBJECT
public:
    drc();
    drc(drawingField *drawing,layout *la);
    ~drc();
    drawingField *drawing;
    layout *la;
    booleanHandler *booleanTool;
//! error layer
/*!
  On this layer all errors are marked.
*/
    int errorLayer;
//! error count
/*!
  Sum of detected errors.
*/
    int errorCount;
//! errors
/*!
  Error on last check.
*/
    int error;
//! ruleName
/*!
  The name of the next rule.
*/
    QString ruleName;
//! result
/*!
  This string contains a little report of the last test results.
*/
    QString result;
public slots:
//! set error layer
/*!
  The error Layer is set to the active Layer.
*/
    void setErrorLayerToActiveLayer(){
		errorLayer=drawing->activeLayer;
		drawing->macroAdd("layout->drcTool->setErrorLayerToActiveLayer();");}
    void setRuleName(QString s);
//! no Element 
/*!
  Tests ,if there are elements on the layer.
@see @link "No Element;DRC: No Element"
*/
    void noElementOnLayer(int layer);
//! no Element on active
/*!
  Tests ,if there are elements on the active layer.
@see @link "No Element;DRC: No Element"
*/
    void noElementOnActiveLayer();
//! no Path 
/*!
  Tests ,if there are path elements on the layer.
@see @link "No Path;DRC: No Path"
*/
    void noPathOnLayer(int layer);
//! no Path on active
/*!
  Tests ,if there are path elements on the active layer.
@see @link "No Path;DRC: No Path"
*/
    void noPathOnActiveLayer();
//! no Box Element 
/*!
  Tests ,if there are box elements on the layer.
@see @link "No Box;DRC: No Box"
*/
    void noBoxOnLayer(int layer);
//! no Box on active
/*!
  Tests ,if there are box elements on the active layer.
@see @link "No Box;DRC: No Box"
*/
    void noBoxOnActiveLayer();
//! no Polygons 
/*!
  Tests ,if there are polygons on the layer.
@see @link "No Polygon;DRC: No Polygon"
*/
    void noPolygonOnLayer(int layer);
//! no Polygons on active
/*!
  Tests ,if there are polygons on the active layer.
@see @link "No Polygon;DRC: No Polygon"
*/
    void noPolygonOnActiveLayer();
//! no Text 
/*!
  Tests ,if there are text elements on the layer.
*/
    void noTextOnLayer(int layer);
//! no Text on active
/*!
  Tests ,if there are text elements on the active layer.
@see @link "No Text;DRC: No Text"
*/
    void noTextOnActiveLayer();
//! show reports
/*!
  Shows a messagebox with the results of the design rule checker.
*/
    void showReport();
//! get reports
/*!
@return result, it is crop of all no errors if it is longer than 40 lines.
*/
    QString getReport();
//! minimum Distance
/*!
  Tests, if all elements between layer1 and layer2 have a minimum distance
@see @link "Minimum Distance;DRC: Minimum Distance"
*/
    void minimumDistance(int distance,int layer1, int layer2);
//! minimum Distance or Overlap
/*!
  Tests, if all elements between layer1 and layer2 have a minimum distance,
an overlap is not marked as an error.
@see @link "Minimum Distance Or Overlap;DRC: Minimum Distance Or Overlap"
*/
    void minimumDistanceOrOverlap(int distance,int layer1, int layer2,bool mode=true);
//! minimum Size
/*!
  Tests, if all elements on layer have a minimum size. If mergeBefure is true, all elements are merged. If sharpAngles is true, sharp angles will also be marked as an error.
@see @link "Minimum Size;DRC: Minimum Size"
*/
    void minimumSize(int size,int layer, bool mergeBefore=false, bool sharpAngles=true);
//! minimum Overlap
/*!
  Tests, if all elements between layer1 and layer2 have a minimum overlap
@see @link "Minimum Overlap;DRC: Minimum Overlap"
*/
    void minimumOverlap(int overlap,int layer1, int layer2);
//! inside with Distance
/*!
  Tests, if all elements on insidelayer are inside in one of layer1 to layer 3 and have a minimum distance.
@see @link "Minimum Size;DRC: Minimum Size"
*/
    void inside(int distance,int insideLayer, int layer1, int layer2=-1, int layer3=-1);
//! Overlapping elements
/*!
  Tests, if there are overlaping elements on layer1.
@see @link "Overlapping Elements;DRC: Overlapping Elements"
*/
    void overlapingElements(int layer);
//! layer combination
/*!
  Tests, if there exists regions on all layers.
@see @link "Layer Combination;DRC: Layer Combination"
*/
    void layerCombination(int layer1,int layer2, int layer3=-1,int layer4=-1, int layer5=-1);
//! Overlapping elements on active
/*!
  Tests ,if there are overlaping elements on the active layer.
@see @link "Overlapping Elements;DRC: Overlapping Elements"
*/
    void overlapingElementsOnActiveLayer();
//! Minimum element Distance
/*!
  Tests, if there are elements on layer with a lower distance.
@see @link "Minimum Elements Distance;DRC: Minimum Elements Distance"
*/
    void minimumElementDistance(int distance,int layer,bool mergeBefore=false);
//! Minimum overlap element Distance
/*!
  Performs an boolean and operation of the two layers and tests, if its distance.
@see @link "Overlap Distance;DRC: Overlap Distance"
*/
    void minimumOverlapDistance(int distance,int layer1,int layer2);
//! Minimum Enclose
/*!
  layer1 must enclose layer2 by minimum of distance
@see @link "Enclosure;DRC: Enclosure"
*/
    void minimumEnclosure(int distance,int layer1,int layer2);
//! Minimum element Distance on active
/*!
 Tests, if there are elements on active layer with a lower distance.
@see @link "Minimum Elements Distance;DRC: Minimum Elements Distance"
*/
    void minimumElementDistanceOnActiveLayer(int distance);
//! no Circle on active
/*!
  Tests, if there is a polygon with a circular shape on the active layer.
@see @link "No Circle;DRC: No Circle"
*/
    void noCircleOnActiveLayer();
//! only Circle on active
/*!
  Tests, if there are other elements then polygons with a circular shape on the active layer.
@see @link "Only Circle;DRC: Only Circle"
*/
    void onlyCircleOnActiveLayer();

//! no Circle on Layer
/*!
  Tests, if there is a polygon with a circular shape on the layer.
@see @link "No Circle;DRC: No Circle"
*/
    void noCircleOnLayer(int layer);
//! only Circle on active
/*!
  Tests, if there are other elements then polygons with a circular shape on the  layer.
@see @link "Only Circle;DRC: Only Circle"
*/
    void onlyCircleOnLayer(int layer);
//! onGrid
/*!
  Tests, if all points on the layer are on the grid.
@see @link "On Grid;DRC: On Grid"
*/
    void onGrid(int grid,int layer);

//! no Holes on Layer
/*!
  Tests, if there is a polygon with a hole on the layer.
@see @link "DRC: No Holes;DRC: No Holes"
*/
    void noHolesOnLayer(int layer,bool mergeBefore=false);
//! no Minimun Notch on Layer
/*!
  Tests for notches smaller notchsize in polygon/path elements on the layer.
@see @link "DRC: Minimum Notches;DRC: Minimum Notches"
*/
    void minimumNotchOnLayer(int notchsize, int layer, bool mergeBefore=false);
//! Minimum Perimeter on Layer
/*!
  Tests for perimeter smaller than perimetervalue on layer.
@see @link "DRC: Perimeter Check;DRC: Perimeter Check"
*/
    void minimumPerimeterOnLayer(int layer, int perimetervalue ,bool mergeBefore=false);
//! Maximum Perimeter on Layer
/*!
  Tests for perimeter bigger than perimetervalue on layer.
@see @link "DRC: Perimeter Check;DRC: Perimeter Check"
*/
    void maximumPerimeterOnLayer(int layer, int perimeter,bool mergeBefore=false);
//! Minimum Area on Layer
/*!
  Tests for elements with an area smaller than areavalue on layer.
@see @link "DRC: Area Check;DRC: Area Check"
*/
    void minimumAreaOnLayer(int layer, double areavalue ,bool mergeBefore=false);
//! Maximum Area on Layer
/*!
   Tests for elements with an area bigger than areavalue on layer.
@see @link "DRC: Area Check;DRC: Area Check"
*/
    void maximumAreaOnLayer(int layer, double areavalue ,bool mergeBefore=false);
//! check 90° Angle on Layer
/*!
  Tests for elements with non 90°angle to the axis.
@see @link "DRC: Angle Check;DRC: Angle Check"
*/
    void angle90OnLayer(int layer,bool mergeBefore=false);
//! check 45° Angle on Layer
/*!
  Tests for elements with non 45°angle to the axis.
@see @link "DRC: Angle Check;DRC: Angle Check" 
*/
    void angle45OnLayer(int layer,bool mergeBefore=false);
//! maximum Angle on Layer
/*!
  Tests for elements with angle bigger anglevalue on layer.
@see @link "DRC: Angle Check;DRC: Angle Check"
*/
    void maximumAngleOnLayer(double anglevalue, int layer, bool mergeBefore=false);
//! maximum Dimension on Layer
/*!
  Tests, for element with axis dimension bigger a specified value.
@see @link "DRC: Dimension Check;DRC: Dimension Check" 
*/
    void maximumDimensionOnLayer(int length,int width, int layer, bool mergeBefore=false);
//! minimum Dimension on Layer
/*!
    Tests, for element with axis dimension smaller a specified value.
@see @link "DRC: Dimension Check;DRC: Dimension Check" 
*/
    void minimumDimensionOnLayer(int length,int width, int layer, bool mergeBefore=false);

    void noCircleOnActiveLayerGui();

    void onlyCircleOnActiveLayerGui();


    void noElementOnActiveLayerGui();


    void noPathOnActiveLayerGui();


    void noBoxOnActiveLayerGui();


    void noPolygonOnActiveLayerGui();


    void noTextOnActiveLayerGui();

    void overlapingElementsOnActiveLayerGui();

    void updateGui();

private:
    bool record;
    QString orginalCellname;
    QString workCellname;
    void prepareCheck();
    void completeCheck();
    int oldActiveLayer;
    int oldMode;
    elementList *reportedErrors;
    int countErrors;
public:
    void reportError(QPoint,QPoint, double value);
    void reportError(QPoint, double value);
    void reportErrorDeg(QPoint, double value);
    void addError();

};

#endif
