00001
00002
00003
00004
00005
00006
00007 #include "ColorFilter.h"
00008 #include "DocumentModelSegments.h"
00009 #include "EngaugeAssert.h"
00010 #include "Logger.h"
00011 #include <QApplication>
00012 #include <QGraphicsScene>
00013 #include <QProgressDialog>
00014 #include "Segment.h"
00015 #include "SegmentFactory.h"
00016
00017 using namespace std;
00018
00019 SegmentFactory::SegmentFactory(QGraphicsScene &scene,
00020 bool isGnuplot) :
00021 m_scene (scene),
00022 m_isGnuplot (isGnuplot)
00023 {
00024 LOG4CPP_INFO_S ((*mainCat)) << "SegmentFactory::SegmentFactory";
00025 }
00026
00027 int SegmentFactory::adjacentRuns(bool *columnBool,
00028 int yStart,
00029 int yStop,
00030 int height)
00031 {
00032 int runs = 0;
00033 bool inRun = false;
00034 for (int y = yStart - 1; y <= yStop + 1; y++) {
00035 if ((0 <= y) && (y < height)) {
00036 if (!inRun && columnBool [y]) {
00037 inRun = true;
00038 ++runs;
00039 } else if (inRun && !columnBool [y]) {
00040 inRun = false;
00041 }
00042 }
00043 }
00044
00045 return runs;
00046 }
00047
00048 Segment *SegmentFactory::adjacentSegment(SegmentVector &lastSegment,
00049 int yStart,
00050 int yStop,
00051 int height)
00052 {
00053 for (int y = yStart - 1; y <= yStop + 1; y++) {
00054 if ((0 <= y) && (y < height)) {
00055
00056 ENGAUGE_ASSERT (y < height);
00057 if (lastSegment [y]) {
00058 return lastSegment [y];
00059 }
00060 }
00061 }
00062
00063 return 0;
00064 }
00065
00066 int SegmentFactory::adjacentSegments(SegmentVector &lastSegment,
00067 int yStart,
00068 int yStop,
00069 int height)
00070 {
00071 int adjacentSegments = 0;
00072
00073 bool inSegment = false;
00074 for (int y = yStart - 1; y <= yStop + 1; y++) {
00075 if ((0 <= y) && (y < height)) {
00076
00077 ENGAUGE_ASSERT (y < height);
00078 if (!inSegment && lastSegment [y]) {
00079
00080 inSegment = true;
00081 ++adjacentSegments;
00082 } else if (inSegment && !lastSegment [y]) {
00083 inSegment = false;
00084 }
00085 }
00086 }
00087
00088 return adjacentSegments;
00089 }
00090
00091 QList<QPoint> SegmentFactory::fillPoints(const DocumentModelSegments &modelSegments,
00092 QList<Segment*> segments)
00093 {
00094 LOG4CPP_INFO_S ((*mainCat)) << "SegmentFactory::fillPoints";
00095
00096 QList<QPoint> list;
00097 QList<Segment*>::iterator itr;
00098 for (itr = segments.begin (); itr != segments.end(); itr++) {
00099
00100 Segment *segment = *itr;
00101 ENGAUGE_CHECK_PTR(segment);
00102 list += segment->fillPoints(modelSegments);
00103 }
00104
00105 return list;
00106 }
00107
00108 void SegmentFactory::finishRun(bool *lastBool,
00109 bool *nextBool,
00110 SegmentVector &lastSegment,
00111 SegmentVector &currSegment,
00112 int x,
00113 int yStart,
00114 int yStop,
00115 int height,
00116 const DocumentModelSegments &modelSegments,
00117 int* madeLines)
00118 {
00119 LOG4CPP_DEBUG_S ((*mainCat)) << "SegmentFactory::finishRun"
00120 << " column=" << x
00121 << " rows=" << yStart << "-" << yStop
00122 << " runsOnLeft=" << adjacentRuns (nextBool, yStart, yStop, height)
00123 << " runsOnRight=" << adjacentSegments (lastSegment, yStart, yStop, height);
00124
00125
00126
00127
00128
00129
00130 if (adjacentRuns(lastBool, yStart, yStop, height) > 1) {
00131 return;
00132 }
00133
00134
00135 if (adjacentRuns(nextBool, yStart, yStop, height) > 1) {
00136 return;
00137 }
00138
00139 Segment *seg;
00140 if (adjacentSegments(lastSegment, yStart, yStop, height) == 0) {
00141
00142
00143 seg = new Segment(m_scene,
00144 (int) (0.5 + (yStart + yStop) / 2.0),
00145 m_isGnuplot);
00146 ENGAUGE_CHECK_PTR (seg);
00147
00148 } else {
00149
00150
00151 seg = adjacentSegment(lastSegment, yStart, yStop, height);
00152
00153 ++(*madeLines);
00154 ENGAUGE_CHECK_PTR(seg);
00155 seg->appendColumn(x, (int) (0.5 + (yStart + yStop) / 2.0), modelSegments);
00156 }
00157
00158 for (int y = yStart; y <= yStop; y++) {
00159
00160 ENGAUGE_ASSERT (y < height);
00161 currSegment [y] = seg;
00162 }
00163 }
00164
00165 void SegmentFactory::loadBool (const ColorFilter &filter,
00166 bool *columnBool,
00167 const QImage &image,
00168 int x)
00169 {
00170 for (int y = 0; y < image.height(); y++) {
00171 if (x < 0) {
00172 columnBool [y] = false;
00173 } else {
00174 columnBool [y] = filter.pixelFilteredIsOn (image, x, y);
00175 }
00176 }
00177 }
00178
00179 void SegmentFactory::loadSegment (SegmentVector &columnSegment,
00180 int height)
00181 {
00182 for (int y = 0; y < height; y++) {
00183 columnSegment [y] = 0;
00184 }
00185 }
00186
00187 void SegmentFactory::makeSegments (const QImage &imageFiltered,
00188 const DocumentModelSegments &modelSegments,
00189 QList<Segment*> &segments,
00190 bool useDlg)
00191 {
00192 LOG4CPP_INFO_S ((*mainCat)) << "SegmentFactory::makeSegments";
00193
00194
00195 int madeLines = 0;
00196 int shortLines = 0;
00197 int foldedLines = 0;
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 int width = imageFiltered.width();
00212 int height = imageFiltered.height();
00213
00214 QProgressDialog* dlg = 0;
00215 if (useDlg)
00216 {
00217
00218 dlg = new QProgressDialog("Scanning segments in image", "Cancel", 0, width);
00219 ENGAUGE_CHECK_PTR (dlg);
00220 dlg->show();
00221 }
00222
00223 bool* lastBool = new bool [height];
00224 ENGAUGE_CHECK_PTR(lastBool);
00225 bool* currBool = new bool [height];
00226 ENGAUGE_CHECK_PTR(currBool);
00227 bool* nextBool = new bool [height];
00228 ENGAUGE_CHECK_PTR(nextBool);
00229 SegmentVector lastSegment (height);
00230 SegmentVector currSegment (height);
00231
00232 ColorFilter filter;
00233 loadBool(filter, lastBool, imageFiltered, -1);
00234 loadBool(filter, currBool, imageFiltered, 0);
00235 loadBool(filter, nextBool, imageFiltered, 1);
00236 loadSegment(lastSegment, height);
00237
00238 for (int x = 0; x < width; x++) {
00239
00240 if (useDlg) {
00241
00242
00243 dlg->setValue(x);
00244 qApp->processEvents();
00245
00246 if (dlg->wasCanceled()) {
00247
00248
00249 break;
00250 }
00251 }
00252
00253 matchRunsToSegments(x,
00254 height,
00255 lastBool,
00256 lastSegment,
00257 currBool,
00258 currSegment,
00259 nextBool,
00260 modelSegments,
00261 &madeLines,
00262 &foldedLines,
00263 &shortLines,
00264 segments);
00265
00266
00267 scrollBool(lastBool, currBool, height);
00268 scrollBool(currBool, nextBool, height);
00269 if (x + 1 < width) {
00270 loadBool(filter, nextBool, imageFiltered, x + 1);
00271 }
00272 scrollSegment(lastSegment, currSegment, height);
00273 }
00274
00275 if (useDlg) {
00276
00277 dlg->setValue(width);
00278 delete dlg;
00279 }
00280
00281 removeEmptySegments (segments);
00282
00283 LOG4CPP_INFO_S ((*mainCat)) << "SegmentFactory::makeSegments"
00284 << " linesCreated=" << madeLines
00285 << " linesTooShortSoRemoved=" << shortLines
00286 << " linesFoldedTogether=" << foldedLines;
00287
00288 delete[] lastBool;
00289 delete[] currBool;
00290 delete[] nextBool;
00291 }
00292
00293 void SegmentFactory::matchRunsToSegments(int x,
00294 int height,
00295 bool *lastBool,
00296 SegmentVector &lastSegment,
00297 bool* currBool,
00298 SegmentVector &currSegment,
00299 bool *nextBool,
00300 const DocumentModelSegments &modelSegments,
00301 int *madeLines,
00302 int *foldedLines,
00303 int *shortLines,
00304 QList<Segment*> &segments)
00305 {
00306 loadSegment(currSegment,
00307 height);
00308
00309 int yStart = 0;
00310 bool inRun = false;
00311 for (int y = 0; y < height; y++) {
00312
00313 ENGAUGE_ASSERT (y < height);
00314 if (!inRun && currBool [y]) {
00315 inRun = true;
00316 yStart = y;
00317 }
00318
00319 if ((y + 1 >= height) || !currBool [y + 1]) {
00320 if (inRun) {
00321 finishRun(lastBool,
00322 nextBool,
00323 lastSegment,
00324 currSegment,
00325 x, yStart,
00326 y,
00327 height,
00328 modelSegments,
00329 madeLines);
00330 }
00331
00332 inRun = false;
00333 }
00334 }
00335
00336 removeUnneededLines(lastSegment,
00337 currSegment,
00338 height,
00339 foldedLines,
00340 shortLines,
00341 modelSegments,
00342 segments);
00343 }
00344
00345 void SegmentFactory::removeEmptySegments (QList<Segment*> &segments) const
00346 {
00347 LOG4CPP_DEBUG_S ((*mainCat)) << "SegmentFactory::removeUnneededLines";
00348
00349 for (int i = segments.count(); i > 0;) {
00350
00351 --i;
00352 Segment *segment = segments.at (i);
00353
00354
00355 if (segment->lineCount () == 0) {
00356
00357
00358 delete segment;
00359
00360 segments.removeAt (i);
00361 }
00362 }
00363 }
00364
00365 void SegmentFactory::removeUnneededLines(SegmentVector &lastSegment,
00366 SegmentVector &currSegment,
00367 int height,
00368 int *foldedLines,
00369 int *shortLines,
00370 const DocumentModelSegments &modelSegments,
00371 QList<Segment*> &segments)
00372 {
00373 LOG4CPP_DEBUG_S ((*mainCat)) << "SegmentFactory::removeUnneededLines";
00374
00375 Segment *segLast = 0;
00376 for (int yLast = 0; yLast < height; yLast++) {
00377
00378 ENGAUGE_ASSERT (yLast < height);
00379 if (lastSegment [yLast] && (lastSegment [yLast] != segLast)) {
00380
00381 segLast = lastSegment [yLast];
00382
00383
00384 bool found = false;
00385 for (int yCur = 0; yCur < height; yCur++) {
00386
00387 ENGAUGE_ASSERT (yCur < height);
00388 if (segLast == currSegment [yCur]) {
00389 found = true;
00390 break;
00391 }
00392 }
00393
00394 if (!found) {
00395
00396 ENGAUGE_CHECK_PTR(segLast);
00397 if (segLast->length() < (modelSegments.minLength() - 1) * modelSegments.pointSeparation()) {
00398
00399
00400
00401
00402 *shortLines += segLast->lineCount();
00403 delete segLast;
00404 lastSegment [yLast] = 0;
00405
00406 } else {
00407
00408
00409 segLast->removeUnneededLines(foldedLines);
00410
00411
00412 segments.push_back (segLast);
00413
00414 }
00415 }
00416 }
00417 }
00418 }
00419
00420 void SegmentFactory::scrollBool(bool *left,
00421 bool *right,
00422 int height)
00423 {
00424 for (int y = 0; y < height; y++) {
00425 left [y] = right [y];
00426 }
00427 }
00428
00429 void SegmentFactory::scrollSegment(SegmentVector &left,
00430 SegmentVector &right,
00431 int height)
00432 {
00433 for (int y = 0; y < height; y++) {
00434 left [y] = right [y];
00435 }
00436 }
00437
00438 void SegmentFactory::clearSegments (QList<Segment*> &segments)
00439 {
00440 LOG4CPP_DEBUG_S ((*mainCat)) << "SegmentFactory::clearSegments";
00441
00442 QList<Segment*>::iterator itr;
00443 for (itr = segments.begin(); itr != segments.end(); itr++) {
00444
00445 Segment *segment = *itr;
00446
00447 delete segment;
00448 }
00449
00450 segments.clear ();
00451 }