void ConePrimitiveShape::BitmapExtent(float epsilon, GfxTL::AABox< GfxTL::Vector2Df > *bbox, MiscLib::Vector< std::pair< float, float > > *params, size_t *uextent, size_t *vextent) { *uextent = std::ceil((bbox->Max()[0] - bbox->Min()[0]) / epsilon); // no wrappig along u direction *vextent = std::ceil((bbox->Max()[1] - bbox->Min()[1]) / epsilon) + 1; // add one for wrapping if((*vextent) * (*uextent) > 1e6 && m_cone.Angle() < float(M_PI / 4)) { // try to reparameterize // try to find cut in the outer regions MiscLib::Vector< float > angularParams;//(params->size()); angularParams.reserve(params->size()); float outer = 3.f * std::max(abs(bbox->Min()[0]), abs(bbox->Max()[0])) / 4.f; for(size_t i = 0; i < params->size(); ++i) if((*params)[i].first > outer) angularParams.push_back(((*params)[i].second / m_cone.RadiusAtLength((*params)[i].first)) + float(M_PI)); std::sort(angularParams.begin(), angularParams.end()); // try to find a large gap float maxGap = 0; float lower, upper; for(size_t i = 1; i < angularParams.size(); ++i) { float gap = angularParams[i] - angularParams[i - 1]; if(gap > maxGap) { maxGap = gap; lower = angularParams[i - 1]; upper = angularParams[i]; } } // reparameterize with new angular cut float newCut = (lower + upper) / 2.f; m_cone.RotateAngularDirection(newCut); bbox->Min()[1] = std::numeric_limits< float >::infinity(); bbox->Max()[1] = -std::numeric_limits< float >::infinity(); for(size_t i = 0; i < params->size(); ++i) { float r = m_cone.RadiusAtLength((*params)[i].first); (*params)[i].second = ((*params)[i].second / r) + float(M_PI) - newCut; if((*params)[i].second < 0) (*params)[i].second = 2 * float(M_PI) + (*params)[i].second; (*params)[i].second = ((*params)[i].second - float(M_PI)) * r; if((*params)[i].second < bbox->Min()[1]) bbox->Min()[1] = (*params)[i].second; if((*params)[i].second > bbox->Max()[1]) bbox->Max()[1] = (*params)[i].second; } *vextent = std::floor((bbox->Max()[1] - bbox->Min()[1]) / epsilon) + 1; } }
void Components(const MiscLib::Vector< char > &bitmap, size_t uextent, size_t vextent, bool uwrap, bool vwrap, MiscLib::Vector< int > *componentsImg, MiscLib::Vector< std::pair< int, size_t > > *labels) { componentsImg->resize(uextent * vextent); MiscLib::Vector< std::pair< int, size_t > > tempLabels; tempLabels.reserve(componentsImg->size() / 2 + 1); // this is the maximum of possible tempLabels tempLabels.push_back(std::make_pair(0, size_t(0))); // use an eight neighborhood // first row is special // first pixel is special // wrapping does not make sense in the first row: no pixels have been // assigned components yet int curLabel = 0; if(bitmap[0]) { (*componentsImg)[0] = ++curLabel; tempLabels.push_back(std::make_pair(curLabel, size_t(1))); } else { (*componentsImg)[0] = 0; ++tempLabels[0].second; } // handle first row for(size_t i = 1; i < uextent; ++i) { // in the first row only the previous pixel has to be considered if(bitmap[i]) { if((*componentsImg)[i - 1]) { (*componentsImg)[i] = (*componentsImg)[i - 1]; ++tempLabels[(*componentsImg)[i]].second; } else { (*componentsImg)[i] = ++curLabel; tempLabels.push_back(std::make_pair(curLabel, size_t(1))); } } else { (*componentsImg)[i] = 0; ++tempLabels[0].second; } } size_t prevRow, row = 0; size_t jend = vwrap? vextent - 1 : vextent; for(size_t j = 1; j < jend; ++j) { prevRow = row; row = prevRow + uextent; // first pixel in row gets different treatment if(bitmap[row]) { if((*componentsImg)[prevRow]) // pixel above in component? { (*componentsImg)[row] = (*componentsImg)[prevRow]; ++tempLabels[(*componentsImg)[row]].second; } else { int n[2]; n[0] = (*componentsImg)[prevRow + 1]; if(uwrap) n[1] = (*componentsImg)[prevRow + uextent - 1]; (*componentsImg)[row] = Label(n, uwrap? 2 : 1, &curLabel, &tempLabels); } } else { (*componentsImg)[row] = 0; ++tempLabels[0].second; } for(size_t i = 1; i < uextent - 1; ++i) { if(!bitmap[row + i]) { (*componentsImg)[row + i] = 0; ++tempLabels[0].second; continue; } int n[4]; n[0] = (*componentsImg)[row + i - 1]; n[1] = (*componentsImg)[prevRow + i - 1]; n[2] = (*componentsImg)[prevRow + i]; n[3] = (*componentsImg)[prevRow + i + 1]; (*componentsImg)[row + i] = Label(n, 4, &curLabel, &tempLabels); } // last pixel in the row if(!bitmap[row + uextent - 1]) { (*componentsImg)[row + uextent - 1] = 0; ++tempLabels[0].second; continue; } int n[5]; n[0] = (*componentsImg)[row + uextent - 2]; n[1] = (*componentsImg)[prevRow + uextent - 2]; n[2] = (*componentsImg)[prevRow + uextent - 1]; if(uwrap) { n[3] = (*componentsImg)[prevRow]; n[4] = (*componentsImg)[row]; } (*componentsImg)[row + uextent - 1] = Label(n, uwrap? 5 : 3, &curLabel, &tempLabels); } // last row if(vwrap) // in case of vwrapping the last row is computed with almost full // neighborhood { prevRow = (vextent - 2) * uextent; row = (vextent - 1) * uextent; // first pixel if(bitmap[row]) { int n[6]; n[0] = (*componentsImg)[prevRow]; n[1] = (*componentsImg)[prevRow + 1]; n[2] = (*componentsImg)[0]; n[3] = (*componentsImg)[1]; if(uwrap) { n[4] = (*componentsImg)[prevRow + uextent - 1]; n[5] = (*componentsImg)[uextent - 1]; } (*componentsImg)[row] = Label(n, uwrap? 6 : 4, &curLabel, &tempLabels); } else { (*componentsImg)[row] = 0; ++tempLabels[0].second; } for(size_t i = 1; i < uextent - 1; ++i) { if(!bitmap[row + i]) { (*componentsImg)[row + i] = 0; ++tempLabels[0].second; continue; } int n[7]; n[0] = (*componentsImg)[row + i - 1]; n[1] = (*componentsImg)[prevRow + i - 1]; n[2] = (*componentsImg)[prevRow + i]; n[3] = (*componentsImg)[prevRow + i + 1]; n[4] = (*componentsImg)[i - 1]; n[5] = (*componentsImg)[i]; n[6] = (*componentsImg)[i + 1]; (*componentsImg)[row + i] = Label(n, 7, &curLabel, &tempLabels); } // last pixel if(!bitmap[row + uextent - 1]) { (*componentsImg)[row + uextent - 1] = 0; ++tempLabels[0].second; } else { int n[8]; n[0] = (*componentsImg)[row + uextent - 2]; n[1] = (*componentsImg)[prevRow + uextent - 2]; n[2] = (*componentsImg)[prevRow + uextent - 1]; n[3] = (*componentsImg)[uextent - 2]; n[4] = (*componentsImg)[uextent - 1]; if(uwrap) { n[5] = (*componentsImg)[prevRow]; n[6] = (*componentsImg)[row]; n[7] = (*componentsImg)[0]; } (*componentsImg)[row + uextent - 1] = Label(n, uwrap? 8 : 5, &curLabel, &tempLabels); } } // reduce the tempLabels for(size_t i = tempLabels.size() - 1; i > 0; --i) tempLabels[i].first = ReduceLabel(i, tempLabels); MiscLib::Vector< int > condensed(tempLabels.size()); labels->clear(); labels->reserve(condensed.size()); int count = 0; for(size_t i = 0; i < tempLabels.size(); ++i) if(i == (size_t)tempLabels[i].first) { labels->push_back(std::make_pair(count, tempLabels[i].second)); condensed[i] = count; ++count; } else (*labels)[condensed[tempLabels[i].first]].second += tempLabels[i].second; // set new component ids for(size_t i = 0; i < componentsImg->size(); ++i) (*componentsImg)[i] = condensed[tempLabels[(*componentsImg)[i]].first]; }