degate 0.1.1
Line.cc
Go to the documentation of this file.
00001 /*
00002 
00003  This file is part of the IC reverse engineering tool degate.
00004 
00005  Copyright 2008, 2009, 2010 by Martin Schobert
00006 
00007  Degate is free software: you can redistribute it and/or modify
00008  it under the terms of the GNU General Public License as published by
00009  the Free Software Foundation, either version 3 of the License, or
00010  any later version.
00011 
00012  Degate is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU General Public License for more details.
00016 
00017  You should have received a copy of the GNU General Public License
00018  along with degate. If not, see <http://www.gnu.org/licenses/>.
00019 
00020  */
00021 
00022 #include "Line.h"
00023 #include "globals.h"
00024 #include <math.h>
00025 #include <stdlib.h>
00026 
00027 using namespace degate;
00028 
00029 Line::Line() :
00030   from_x(0),
00031   from_y(0),
00032   to_x(0),
00033   to_y(0),
00034   diameter(0),
00035   d_x(0),
00036   d_y(0) {
00037   calculate_bounding_box();
00038 }
00039 
00040 Line::Line(int _from_x, int _from_y, int _to_x, int _to_y, unsigned int _diameter) :
00041   from_x(_from_x),
00042   from_y(_from_y),
00043   to_x(_to_x),
00044   to_y(_to_y),
00045   diameter(_diameter),
00046   d_x(_to_x - _from_x),
00047   d_y(_to_y - _from_y) {
00048   calculate_bounding_box();
00049 }
00050 
00051 bool Line::in_shape(int x, int y, int max_distance) const {
00052 
00053   /*
00054     How to check if a point is on a line:
00055     y = m*x + n
00056     m = dy / dx
00057     n = y0 - m*x0
00058     y' = m*x' + n
00059 
00060     |y' - y| < epsilon?
00061   */
00062 
00063   /*
00064     Check if it is a vertical line (dy ~~ 0). If it is true, the bounding box
00065     describes the line. The same applies to horiontal lines.
00066   */
00067 
00068   if(is_vertical() || is_horizontal()) {
00069     return bounding_box.in_shape(x, y, max_distance);
00070   }
00071   else {
00072 
00073     // check if x is outside the x-range
00074     if(x < std::min(from_x,to_x) ||
00075        x > std::max(from_x, to_x))
00076        return false;
00077 
00078     double m = d_y / d_x;
00079     double n = (double)from_y - m * (double)from_x;
00080     double y_dash = m * (double) x + n;
00081 
00082     if(fabs(y_dash - y) <= diameter / 2 + max_distance)
00083       return true;
00084     else
00085       return false;
00086   }
00087 }
00088 
00089 bool Line::in_bounding_box(BoundingBox const& bbox) const {
00090   return bounding_box.in_bounding_box(bbox);
00091 }
00092 
00093 
00094 BoundingBox const& Line::get_bounding_box() const {
00095   return bounding_box;
00096 }
00097 
00098 bool Line::is_vertical() const {
00099   return to_x - from_x == 0;
00100 }
00101 
00102 bool Line::is_horizontal() const {
00103   return to_y - from_y == 0;
00104 }
00105 
00106 void Line::set_diameter(unsigned int diameter) {
00107   this->diameter = diameter;
00108   calculate_bounding_box();
00109 }
00110 
00111 unsigned int Line::get_diameter() const {
00112   return diameter;
00113 }
00114 
00115 int Line::get_from_x() const {
00116   return from_x;
00117 }
00118 
00119 int Line::get_from_y() const {
00120   return from_y;
00121 }
00122 
00123 int Line::get_to_x() const {
00124   return to_x;
00125 }
00126 
00127 int Line::get_to_y() const {
00128   return to_y;
00129 }
00130 
00131 void Line::set_from_x(int from_x) {
00132   this->from_x = from_x;
00133   d_x = to_x - from_x;
00134   calculate_bounding_box();
00135 }
00136 
00137 void Line::set_to_x(int to_x) {
00138   this->to_x = to_x;
00139   d_x = to_x - from_x;
00140   calculate_bounding_box();
00141 }
00142 
00143 void Line::set_from_y(int from_y) {
00144   this->from_y = from_y;
00145   d_y = to_y - from_y;
00146   calculate_bounding_box();
00147 }
00148 
00149 void Line::set_to_y(int to_y) {
00150   this->to_y = to_y;
00151   d_y = to_y - from_y;
00152   calculate_bounding_box();
00153 }
00154 
00155 void Line::shift_y(int delta_y) {
00156   from_y += delta_y;
00157   to_y += delta_y;
00158   calculate_bounding_box();
00159 }
00160 
00161 void Line::shift_x(int delta_x) {
00162   from_x += delta_x;
00163   to_x += delta_x;
00164   calculate_bounding_box();
00165 }
00166 
00167 
00168 void Line::calculate_bounding_box() {
00169   int radius = diameter >> 1;
00170 
00171   if(is_vertical())
00172     bounding_box = BoundingBox(std::max(from_x  - radius, 0),
00173                                std::max(to_x + radius, 0), from_y, to_y);
00174   else if(is_horizontal())
00175     bounding_box = BoundingBox(from_x, to_x,
00176                                std::max(from_y - radius, 0),
00177                                std::max(to_y + radius, 0));
00178   else
00179     bounding_box = BoundingBox(from_x, to_x, from_y, to_y);
00180 }
00181 
00182 
00183 unsigned int Line::get_length() const {
00184   return ((labs(from_x - to_x) << 1) + (labs(from_y - to_y) << 1)) >> 1;
00185 }
00186 
00187 Point Line::get_p1() const {
00188   return Point(from_x, from_y);
00189 }
00190 
00191 Point Line::get_p2() const {
00192   return Point(to_x, to_y);
00193 }
00194 
00195 void Line::set_p1(Point const& p) {
00196   set_from_x(p.get_x());
00197   set_from_y(p.get_y());
00198 }
00199 
00200 void Line::set_p2(Point const& p) {
00201   set_to_x(p.get_x());
00202   set_to_y(p.get_y());
00203 }