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