void Path::FastBBox(double &l,double &t,double &r,double &b) { l = t = r = b = 0; bool empty = true; Geom::Point lastP(0, 0); for (int i = 0; i < int(descr_cmd.size()); i++) { int const typ = descr_cmd[i]->getType(); switch ( typ ) { case descr_lineto: { PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[i]); if ( empty ) { l = r = nData->p[Geom::X]; t = b = nData->p[Geom::Y]; empty = false; } else { if ( nData->p[Geom::X] < l ) { l = nData->p[Geom::X]; } if ( nData->p[Geom::X] > r ) { r = nData->p[Geom::X]; } if ( nData->p[Geom::Y] < t ) { t = nData->p[Geom::Y]; } if ( nData->p[Geom::Y] > b ) { b = nData->p[Geom::Y]; } } lastP = nData->p; } break; case descr_moveto: { PathDescrMoveTo *nData = dynamic_cast<PathDescrMoveTo *>(descr_cmd[i]); if ( empty ) { l = r = nData->p[Geom::X]; t = b = nData->p[Geom::Y]; empty = false; } else { if ( nData->p[Geom::X] < l ) { l = nData->p[Geom::X]; } if ( nData->p[Geom::X] > r ) { r = nData->p[Geom::X]; } if ( nData->p[Geom::Y] < t ) { t = nData->p[Geom::Y]; } if ( nData->p[Geom::Y] > b ) { b = nData->p[Geom::Y]; } } lastP = nData->p; } break; case descr_arcto: { PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[i]); if ( empty ) { l = r = nData->p[Geom::X]; t = b = nData->p[Geom::Y]; empty = false; } else { if ( nData->p[Geom::X] < l ) { l = nData->p[Geom::X]; } if ( nData->p[Geom::X] > r ) { r = nData->p[Geom::X]; } if ( nData->p[Geom::Y] < t ) { t = nData->p[Geom::Y]; } if ( nData->p[Geom::Y] > b ) { b = nData->p[Geom::Y]; } } lastP = nData->p; } break; case descr_cubicto: { PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[i]); if ( empty ) { l = r = nData->p[Geom::X]; t = b = nData->p[Geom::Y]; empty = false; } else { if ( nData->p[Geom::X] < l ) { l = nData->p[Geom::X]; } if ( nData->p[Geom::X] > r ) { r = nData->p[Geom::X]; } if ( nData->p[Geom::Y] < t ) { t = nData->p[Geom::Y]; } if ( nData->p[Geom::Y] > b ) { b = nData->p[Geom::Y]; } } /* bug 249665: "...the calculation of the bounding-box for cubic-paths has some extra steps to make it work corretly in Win32 that unfortunately are unnecessary in Linux, generating wrong results. This only shows in Type1 fonts because they use cubic-paths instead of the bezier-paths used by True-Type fonts." */ #ifdef WIN32 Geom::Point np = nData->p - nData->end; if ( np[Geom::X] < l ) { l = np[Geom::X]; } if ( np[Geom::X] > r ) { r = np[Geom::X]; } if ( np[Geom::Y] < t ) { t = np[Geom::Y]; } if ( np[Geom::Y] > b ) { b = np[Geom::Y]; } np = lastP + nData->start; if ( np[Geom::X] < l ) { l = np[Geom::X]; } if ( np[Geom::X] > r ) { r = np[Geom::X]; } if ( np[Geom::Y] < t ) { t = np[Geom::Y]; } if ( np[Geom::Y] > b ) { b = np[Geom::Y]; } #endif lastP = nData->p; } break; case descr_bezierto: { PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[i]); if ( empty ) { l = r = nData->p[Geom::X]; t = b = nData->p[Geom::Y]; empty = false; } else { if ( nData->p[Geom::X] < l ) { l = nData->p[Geom::X]; } if ( nData->p[Geom::X] > r ) { r = nData->p[Geom::X]; } if ( nData->p[Geom::Y] < t ) { t = nData->p[Geom::Y]; } if ( nData->p[Geom::Y] > b ) { b = nData->p[Geom::Y]; } } lastP = nData->p; } break; case descr_interm_bezier: { PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i]); if ( empty ) { l = r = nData->p[Geom::X]; t = b = nData->p[Geom::Y]; empty = false; } else { if ( nData->p[Geom::X] < l ) { l = nData->p[Geom::X]; } if ( nData->p[Geom::X] > r ) { r = nData->p[Geom::X]; } if ( nData->p[Geom::Y] < t ) { t = nData->p[Geom::Y]; } if ( nData->p[Geom::Y] > b ) { b = nData->p[Geom::Y]; } } } break; } } }
bool TissueState::parseFromTrackedCellsFile(const string FileName, const string OriginalFileName) { cleanUp(); // load images QtRasterImage image(FileName.c_str()); if(!image.valid()) { return false; } QtRasterImage original(OriginalFileName.c_str()); if(!original.valid()) { return false; } // prepare pixel frames PixelFrame frame(image); PixelFrame originalFrame(original); TextProgressBar bar; // loop through all pixels of the image Pixel p(frame); PixelValue lastValue=p.data(); while(true) { Pixel lastP(p); ++p; // done? if(!p.inCanvas()) { break; } // get pixel value PixelValue curValue=p.data(); // value changes? if(lastValue!=curValue) { // was bond before? if(lastValue==Pixel::BondValue) { // -> curValue corresponds to a cell id and lastP sits on a boundary pixel CellIndex id = curValue; // cell not yet created and not among the ignored cells? if((_cells.count(id)==0) && (_ignoredCells.count(id)==0)) { if(!addCell(id, lastP, originalFrame)) { return false; } } } lastValue = curValue; } bar.update(p.fractionOfCanvas()); } bar.done(true); // clear unneeded data _vertexMap.clear(); _directedBondMap.clear(); // remove directed bonds without cell (created in addCell as old conjugated bonds; this was needed for the sorting within vertices) std::stack<DirectedBond*> toBeRemoved; for(TissueState::BondIterator it=beginBondIterator(); it!=endBondIterator(); ++it) { if(!bond(it)->cell) { toBeRemoved.push(bond(it)); } } while(!toBeRemoved.empty()) { removeBondWithoutCell(toBeRemoved.top()); toBeRemoved.pop(); } return true; }