HAL
net_layout_point.cpp
Go to the documentation of this file.
2 #include <QGraphicsEllipseItem>
3 #include <QGraphicsLineItem>
4 #include <QBrush>
5 #include <QPen>
6 #include <QSet>
7 #include <QMultiMap>
8 #include <stdlib.h>
9 #include <QDebug>
10 #include <QTextStream>
11 
13 {
14  return QPointF(
15  p.x() * 200 + 50,
16  p.y() * 100 + 50);
17 }
18 
19 namespace hal {
20 
21 uint qHash(const hal::NetLayoutPoint& p)
22 {
23  return qHash(static_cast<QPoint>(p));
24 }
25 
26 uint qHash(const hal::NetLayoutWire& w)
27 {
28  uint retval = qHash(w.endPoint(NetLayoutWire::SourcePoint)) << 1;
29  return retval + (w.isHorizontal() ? 1 : 0);
30 }
31 
32 //------------ Direction -----------------
34  : mDir(numberToDirection(idir))
35 {;}
36 
37 NetLayoutDirection::DirectionType NetLayoutDirection::numberToDirection(int idir)
38 {
39  if (idir < Left || idir > MaxDir) return Undefined;
40  return static_cast<DirectionType>(idir);
41 }
42 
44 {
45  NetLayoutDirection retval = *this;
46  mDir = numberToDirection(mDir + 1);
47  return retval;
48 }
49 
51 {
52  mDir = numberToDirection(mDir + 1);
53  return *this;
54 }
55 
56 QPoint NetLayoutDirection::step(bool omitEndpoint) const
57 {
58  int dy = omitEndpoint ? 2 : 1;
59  switch (mDir) {
60  case Left:
61  return QPoint(-1,0);
62  case Right:
63  return QPoint(1,0);
64  case Up:
65  return QPoint(0,-dy);
66  case Down:
67  return QPoint(0,dy);
68  default:
69  break;
70  }
71  return QPoint();
72 }
73 
74 //------------ Point ---------------------
76  : QPoint(x_,y_)
77 {;}
78 
80  : QPoint(p)
81 {;}
82 
83 NetLayoutPoint NetLayoutPoint::nextPoint(const NetLayoutDirection& dir, bool omitEndpoint) const
84 {
85  QPoint p(*this);
86  return NetLayoutPoint(p + dir.step(omitEndpoint));
87 }
88 
90 {
91  if (y()<0)
92  return (y() - 1) / 2;
93  return (y() + 1) / 2;
94 }
95 
96 NetLayoutPoint NetLayoutPoint::fromBox(const QPoint& boxPosition, bool isInput)
97 {
98  return NetLayoutPoint(boxPosition.x() + (isInput?0:1), boxPosition.y() * 2);
99 }
100 
102 {
103  return y() % 2 == 0;
104 }
105 
107 {
108  int dy = abs(other.y()-y());
109  int dx = abs(other.x()-x());
110  if (isEndpoint())
111  {
112  --dy;
113  if (dy<0)
114  {
115  if (dx==0) return 0;
116  dy = 1;
117  }
118  ++dy;
119  }
120  return dy*2 + dx*4;
121 }
122 
124 {
125  QPointF p0 = scenePoint(*this) - QPointF(r/2,r/2);
126  QGraphicsEllipseItem* retval = new QGraphicsEllipseItem(p0.x(),p0.y(),r,r);
127  retval->setPen(QPen(QBrush(Qt::black),1.));
128  return retval;
129 }
130 
132 {
133  QMultiMap<int, QPair<int,int> > distanceMap;
134  QList<NetLayoutPoint> retval;
135  QSet<int> placed;
136 
137  int n = points.size();
138  for (int i=1; i<n; i++)
139  for (int j=0; j<i; j++)
140  distanceMap.insert(points.at(i).distanceTo(points.at(j)), qMakePair(i,j));
141 
142  /*
143  for (auto it = distanceMap.begin(); it != distanceMap.end(); ++it)
144  {
145  int i = it.value().first;
146  int j = it.value().second;
147  qDebug() << it.key() << i << j << (QPoint) points.at(i) << (QPoint) points.at(j);
148  }
149  */
150 
151  bool isFirst = true;
152  while (retval.size() < points.size())
153  {
154  auto it = distanceMap.begin();
155  if (isFirst)
156  isFirst = false;
157  else
158  {
159  // search entry where exactly one has been placed
160  while(it != distanceMap.end() &&
161  placed.contains(it.value().first) == placed.contains(it.value().second))
162  ++it;
163  }
164 
165  for (int ipair=0; ipair<2; ipair++)
166  {
167  int i = ipair ? it.value().second : it.value().first;
168  if (!placed.contains(i))
169  {
170  retval.append(points.at(i));
171  placed.insert(i);
172  }
173  }
174  distanceMap.erase(it);
175  }
176 
177  return retval;
178 }
179 
180 //------------ Wire ----------------------
182  : mPoint(p), mDir(dir), mIsEndpoint(isEnd)
183 {
184  switch (dir.direction())
185  {
187  mPoint = p.nextPoint(dir);
189  break;
191  mPoint = p.nextPoint(dir, !isEnd);
193  break;
194  default:
195  break;
196  }
197 }
198 
199 bool NetLayoutWire::operator==(const NetLayoutWire& other) const
200 {
201  return (mPoint==other.mPoint &&
202  mDir==other.mDir &&
203  mIsEndpoint==other.mIsEndpoint);
204 }
205 
207 {
208  static const char* cdir = "LRUD";
209  return QString("<%1,%2>-%3-%4").arg(mPoint.x()).arg(mPoint.y()).arg(cdir[mDir.index()]).arg(mIsEndpoint?'X':'-');
210 }
211 
213 {
214  if (mDir.isNull()) return nullptr;
215  NetLayoutPoint p = mPoint.nextPoint(mDir,!mIsEndpoint);
216  QPointF p0 = scenePoint(mPoint);
217  QPointF p1 = scenePoint(p);
218  QGraphicsLineItem* retval = new QGraphicsLineItem(QLineF(p0,p1));
219  retval->setPen(QPen(QBrush(Qt::black),3.));
220  return retval;
221 }
222 
224 {
225  if (pnt == SourcePoint) return mPoint;
226  return NetLayoutPoint(static_cast<QPoint>(mPoint)+mDir.step(!mIsEndpoint));
227 }
228 
229 //------------ Connection ----------------
231 {
232  NetLayoutDirection hDir, vDir;
233 
234  if (pa==pb)
235  {
236  // connection has one junction point and no wire
237  mWaypointLinks.insert(pa,QList<int>());
238  return;
239  }
240 
241  NetLayoutPoint waypoint = pa;
242  int dx = pb.x() - pa.x();
243  int dy = pb.y() - pa.y();
244 
245  NetLayoutDirection vdir, hdir;
246 
247  if (pa.isEndpoint())
248  {
250  waypoint = addWire(waypoint, vdir, false);
251  }
252 
253  if (dx)
254  {
256  for (int i=0; i<abs(dx); i++)
257  waypoint = addWire(waypoint, hdir, true);
258  }
259 
260  dy = pb.y() - waypoint.y();
261  if (abs(dy) > 1)
262  {
264  int ysteps = abs(dy) / 2;
265  for (int i=0; i<ysteps; i++)
266  waypoint = addWire(waypoint, vdir, true);
267  }
268 
269  if (pb.isEndpoint())
270  {
271  dy = pb.y() - waypoint.y();
273  addWire(waypoint, vdir, false);
274  }
275 }
276 
278 {
279  NetLayoutPoint retval;
280  int bestDistance = 0;
281  for (const NetLayoutPoint& testP : mWaypointLinks.keys())
282  {
283  if (testP.isUndefined()) continue;
284  int distance = pnt.distanceTo(testP);
285  if (retval.isUndefined() || distance < bestDistance)
286  {
287  bestDistance = distance;
288  retval = testP;
289  }
290  }
291  if (retval.isUndefined())
292  {
293  qDebug() << "undefined closest point" << pnt.x() << pnt.y();
294  for (const NetLayoutPoint& testP : mWaypointLinks.keys())
295  qDebug() << (QPoint) testP;
296  qDebug() << "-----------";
297  }
298  return retval;
299 }
300 
301 void NetLayoutConnection::add(const NetLayoutConnection& other, bool atomicNet)
302 {
303  for (const NetLayoutWire& w : other)
304  {
305  int n = size();
306  if (atomicNet && !w.isHorizontal() && !w.isEndpoint())
307  {
308  // split vertical wires so that only atomic parts get stored
314  append(wA);
315  append(wB);
316  mWaypointLinks[pA].append(n);
317  mWaypointLinks[pB].append(n);
318  mWaypointLinks[pB].append(n+1);
319  mWaypointLinks[pC].append(n+1);
320  }
321  else
322  {
323  append(w);
324  mWaypointLinks[w.endPoint(NetLayoutWire::SourcePoint)].append(n);
325  mWaypointLinks[w.endPoint(NetLayoutWire::DestinationPoint)].append(n);
326  }
327  }
328 }
329 
330 NetLayoutPoint NetLayoutConnection::addWire(const NetLayoutPoint &pnt, const NetLayoutDirection &dir, bool omitEndpoint)
331 {
332  int n = size();
333  append(NetLayoutWire(pnt,dir,!omitEndpoint));
334  mWaypointLinks[pnt].append(n);
335  NetLayoutPoint nextP = pnt.nextPoint(dir,omitEndpoint);
336  mWaypointLinks[nextP].append(n);
337  return nextP;
338 }
339 
340 //------------ Metric --------------------
342  : mId(id), mFirst(0), mSecond(0)
343 {
344  QMap<int,QMap<int,int>> horizontalMap;
345  QMap<int,QMap<int,int>> verticalMap;
346 
347  for (const NetLayoutWire& w : *con)
348  {
350  if (w.isHorizontal())
351  horizontalMap[p.y()].insert(p.x(),0);
352  else
353  verticalMap[p.x()].insert(p.y(),0);
354  }
355  evaluate(horizontalMap);
356  evaluate(verticalMap);
357 }
358 
360 {
361  if (mSecond > other.mSecond) return true;
362  if (mSecond < other.mSecond) return false;
363  if (mFirst > other.mFirst) return true;
364  if (mFirst < other.mFirst) return false;
365  return (mId < other.mId);
366 }
367 
368 void NetLayoutMetric::evaluate(const QMap<int, QMap<int, int> >& map)
369 {
370  for (QMap<int,int> set : map.values() )
371  {
372  while (!set.isEmpty())
373  {
374 
375  auto it = set.begin();
376  int q = it.key() + 1;
377  int n = 0;
378  auto jt = set.find(q);
379  while (jt != set.end())
380  {
381  ++q;
382  ++n;
383  set.erase(jt);
384  jt = set.find(q);
385  }
386  mFirst += n;
387  mSecond += n*n;
388  set.erase(it);
389  }
390  }
391 }
392 
393 //------------ Factory -------------------
395  : connection(nullptr), mSources(sources), mDestinations(destinations)
396 {
397  mPoints.append(mSources);
398  mPoints.append(mDestinations);
399  mPoints = NetLayoutPoint::orderByDistance(mPoints);
400 
401  /*
402  for (const NetLayoutPoint& p : mPoints)
403  {
404  qDebug() << "point" << (QPoint) p;
405  }
406 */
407 
408  int n=mPoints.size();
409  NetLayoutConnection seedConnection(mPoints.at(0),mPoints.at(1));
410  for (int i=2; i<n; i++)
411  {
412  const NetLayoutPoint& nextPoint = mPoints.at(i);
413  const NetLayoutPoint& juncPoint = seedConnection.closestPoint(nextPoint);
414  NetLayoutConnection nextConnection(nextPoint,juncPoint);
415  seedConnection.add(nextConnection,false);
416  }
418  connection->add(seedConnection,true);
419 }
420 
422 {
423  QTextStream xout(stdout, QIODevice::WriteOnly);
424  xout << stub << "\n";
425  xout << "src:";
426  for (const NetLayoutPoint& pnt : mSources)
427  {
428  xout << QString(" <%1,%2>").arg(pnt.x()).arg(pnt.y());
429  }
430  xout << "\ndst:";
431  for (const NetLayoutPoint& pnt : mDestinations)
432  {
433  xout << QString(" <%1,%2>").arg(pnt.x()).arg(pnt.y());
434  }
435  xout << "\nwire:";
436  for (const NetLayoutWire& w : *connection)
437  {
438  xout << QString(" <%1,%2>%3")
439  .arg(w.endPoint(NetLayoutWire::SourcePoint).x())
440  .arg(w.endPoint(NetLayoutWire::SourcePoint).y())
441  .arg(w.isHorizontal()?'-':'|');
442  }
443  xout << "\n===========================\n";
444 }
445 
447 {
448  clearAll();
449 }
450 
452 {
453  for (NetLayoutConnection* nlc : values())
454  delete nlc;
455  clear();
456 }
457 
458 } // namespace hal
NetLayoutConnectionFactory(const QList< NetLayoutPoint > &sources, const QList< NetLayoutPoint > &destinations)
void dump(const QString &stub) const
NetLayoutConnection * connection
NetLayoutPoint closestPoint(const NetLayoutPoint &pnt) const
void add(const NetLayoutConnection &other, bool atomicNet)
NetLayoutDirection operator++()
NetLayoutDirection(DirectionType dir=Undefined)
QPoint step(bool omitEndpoint=false) const
DirectionType direction() const
NetLayoutMetric(u32 id, const NetLayoutConnection *con)
bool operator<(const NetLayoutMetric &other) const
static QList< NetLayoutPoint > orderByDistance(const QList< NetLayoutPoint > &points)
bool isUndefined() const
NetLayoutPoint nextPoint(const NetLayoutDirection &dir, bool omitEndpoint=false) const
int distanceTo(const NetLayoutPoint &other) const
QGraphicsEllipseItem * graphicsFactory(float r) const
NetLayoutPoint(int x_=INT_MIN, int y_=INT_MIN)
static NetLayoutPoint fromBox(const QPoint &boxPosition, bool isInput)
NetLayoutWire(const NetLayoutPoint &p, const NetLayoutDirection &dir, bool isEnd)
QString toString() const
bool isHorizontal() const
NetLayoutPoint endPoint(WirePointType pnt) const
QGraphicsLineItem * graphicsFactory() const
bool operator==(const NetLayoutWire &other) const
uint qHash(const LaneIndex &ri)
n
Definition: test.py:6
QPointF scenePoint(const QPoint &p)
quint32 u32
i32 id
include set(SRCROOT ${CMAKE_CURRENT_SOURCE_DIR}/src) set(UIROOT $
Definition: CMakeLists.txt:45
void setPen(const QPen &pen)
void setPen(const QPen &pen)
void append(const T &value)
const T & at(int i) const const
int size() const const
T & value() const const
QMap::iterator begin()
QMap::iterator end()
QMap::iterator erase(QMap::iterator pos)
QMap::iterator insert(const Key &key, const T &value)
QList< T > values() const const
typename QMap< Key, T >::iterator insert(const Key &key, const T &value)
int x() const const
int y() const const
qreal x() const const
qreal y() const const
bool contains(const T &value) const const
QSet::iterator insert(const T &value)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const