void CylinderPrimitiveShape::WrapBitmap( const GfxTL::AABox< GfxTL::Vector2Df > &bbox, float epsilon, bool *uwrap, bool *vwrap) const { *uwrap = false; if(bbox.Max()[1] - bbox.Min()[1] >= 2 * M_PI * m_cylinder.Radius() - 2 * epsilon) *vwrap = true; // wrap around angular component else *vwrap = false; }
void ConePrimitiveShape::PreWrapBitmap( const GfxTL::AABox< GfxTL::Vector2Df > &bbox, float epsilon, size_t uextent, size_t vextent, MiscLib::Vector< char > *bmp) const { if(m_cone.Angle() >= float(M_PI / 4)) return; // for wrapping we copy the first pixel to the last one in each v column for(size_t u = 0; u < uextent; ++u) { // determine the coordinates of the last pixel in the column // get the radius of the column float r = m_cone.RadiusAtLength(u * epsilon + bbox.Min()[0]); size_t v = std::floor((2 * float(M_PI) * r - bbox.Min()[1]) / epsilon) + 1; if(v >= vextent) continue; if((*bmp)[u]) (*bmp)[v * uextent + u] = (*bmp)[u]; // do the wrap // if(!(*bmp)[u * vextent + v]) // (*bmp)[u * vextent + v] = (*bmp)[u * vextent]; // do the wrap } }
bool ConePrimitiveShape::InSpace(size_t u, size_t v, float epsilon, const GfxTL::AABox< GfxTL::Vector2Df > &bbox, size_t uextent, size_t vextent, Vec3f *p, Vec3f *n) const { float length, angle; if(m_cone.Angle() >= float(M_PI / 4)) { float uf = ((float(u) + .5f) * epsilon) + bbox.Min()[0]; float vf = ((float(v) + .5f) * epsilon) + bbox.Min()[1]; length = std::sqrt(uf * uf + vf * vf); //angle = std::atan2(vf, uf); angle = std::atan2(uf, vf); //angle = std::acos(GfxTL::Math< float >::Clamp(vf / length, -1.f, 1.f)); } else { length = ((float(u) + .5f) * epsilon) + bbox.Min()[0]; float arcLength = ((float(v) + .5f) * epsilon) + bbox.Min()[1]; angle = (arcLength / m_cone.RadiusAtLength(length)) + float(M_PI); } if(angle > 2 * float(M_PI)) return false; //float angle = ((v * epsilon) / m_cone.RadiusAtLength(std::max(abs(bbox.Min()[0]), abs(bbox.Max()[0]))) // + bbox.Min()[1]); GfxTL::Quaternion< float > q; q.RotationRad(angle, m_cone.AxisDirection()[0], m_cone.AxisDirection()[1], m_cone.AxisDirection()[2]); Vec3f vvec; q.Rotate(m_cone.AngularDirection(), &vvec); *p = std::sin(m_cone.Angle()) * abs(length) * vvec + std::cos(m_cone.Angle()) * length * m_cone.AxisDirection() + m_cone.Center(); // TODO: this is very lazy and should be optimized! m_cone.Normal(*p, n); return true; }
void LowStretchSphereParametrization::WrapComponents(const GfxTL::AABox< GfxTL::Vector2Df > &bbox, float epsilon, size_t uextent, size_t vextent, MiscLib::Vector< int > *componentImg, MiscLib::Vector< std::pair< int, size_t > > *labels) const { // wraps are necessary only in v direction // relabel the components MiscLib::Vector< std::pair< int, size_t > > tempLabels(*labels); // wrap along v float vstartPrev, vendPrev, vstart = 0, vend = 0, vstartNext = 0, vendNext = 0; size_t vsPrev, vePrev, vs = 0, ve = 0, vsNext = 0, veNext = 0; float uangle = (bbox.Min()[0] + .5f * epsilon) / m_sphere->Radius(); float radius = std::sin(uangle) * m_sphere->Radius(); vstartNext = float(-M_PI) * radius; vendNext = float(M_PI) * radius; vsNext = std::min(vextent - 1, (size_t)std::max((intptr_t)0, (intptr_t)((vstartNext - bbox.Min()[1]) / epsilon))); veNext = (size_t)std::max((intptr_t)0, std::min((intptr_t)vextent - 1, (intptr_t)((vendNext - bbox.Min()[1]) / epsilon))); for(size_t u = 0; u < uextent; ++u) { vstartPrev = vstart; vstart = vstartNext; vendPrev = vend; vend = vendNext; vsPrev = vs; vs = vsNext; vePrev = ve; ve = veNext; // determine starting position in the next column if(u < uextent - 1) { float uangleNext = ((u + 1.5f) * epsilon + bbox.Min()[0]) / m_sphere->Radius(); float radiusNext = std::sin(uangle) * m_sphere->Radius(); vstartNext = float(-M_PI) * radius; vendNext = float(M_PI) * radius; vsNext = std::min(vextent - 1, (size_t)std::max((intptr_t)0, (intptr_t)((vstartNext - bbox.Min()[1]) / epsilon))); veNext = (size_t)std::max((intptr_t)0, std::min((intptr_t)vextent - 1, (intptr_t)((vendNext - bbox.Min()[1]) / epsilon))); } if(vstart <= bbox.Min()[1] - epsilon || vend >= bbox.Max()[1] + epsilon || !(*componentImg)[vs * uextent + u]) continue; // check the three neighbors on the other side if((*componentImg)[ve * uextent + u]) AssociateLabel((*componentImg)[vs * uextent + u], (*componentImg)[ve * uextent + u], &tempLabels); if(u > 0 && vstartPrev > bbox.Min()[1] - epsilon && vendPrev < bbox.Min()[1] + epsilon && (*componentImg)[vePrev * uextent + u - 1]) AssociateLabel((*componentImg)[vs * uextent + u], (*componentImg)[vePrev * uextent + u - 1], &tempLabels); if(u < uextent - 1 && vstartNext > bbox.Min()[1] - epsilon && vendNext < bbox.Min()[1] + epsilon && (*componentImg)[veNext * uextent + u + 1]) AssociateLabel((*componentImg)[vs * uextent + u], (*componentImg)[veNext * uextent + u + 1], &tempLabels); } // condense labels 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 == 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 < componentImg->size(); ++i) (*componentImg)[i] = condensed[tempLabels[(*componentImg)[i]].first]; }
void ConePrimitiveShape::WrapComponents( const GfxTL::AABox< GfxTL::Vector2Df > &bbox, float epsilon, size_t uextent, size_t vextent, MiscLib::Vector< int > *componentImg, MiscLib::Vector< std::pair< int, size_t > > *labels) const { if(m_cone.Angle() >= float(M_PI / 4)) return; // for wrapping we copy the first pixel to the last one in each v column for(size_t u = 0; u < uextent; ++u) { // determine the coordinates of the last pixel in the column // get the radius of the column float r = m_cone.RadiusAtLength(u * epsilon + bbox.Min()[0]); size_t v = std::floor((2 * float(M_PI) * r - bbox.Min()[1]) / epsilon) + 1; if(v >= vextent) continue; if((*componentImg)[u]) (*componentImg)[v * uextent + u] = (*componentImg)[u]; // do the wrap } // relabel the components MiscLib::Vector< std::pair< int, size_t > > tempLabels(*labels); int curLabel = tempLabels.size() - 1; for(size_t u = 0; u < uextent; ++u) { float r = m_cone.RadiusAtLength(u * epsilon + bbox.Min()[0]); size_t v = std::floor((2 * float(M_PI) * r - bbox.Min()[1]) / epsilon) + 1; if(v >= vextent) continue; if(!(*componentImg)[v * uextent + u]) continue; // get the neighbors int n[8]; size_t i = 0; if(v >= 1) { size_t prevRow = (v - 1) * uextent; if(u >= 1) n[i++] = (*componentImg)[prevRow + u - 1]; n[i++] = (*componentImg)[prevRow + u]; if(u < uextent - 1) n[i++] = (*componentImg)[prevRow + u + 1]; } size_t row = v * uextent; if(u >= 1) n[i++] = (*componentImg)[row + u - 1]; if(u < uextent - 1) n[i++] = (*componentImg)[row + u + 1]; if(v < vextent - 1) { size_t nextRow = (v + 1) * uextent; if(u >= 1) n[i++] = (*componentImg)[nextRow + u - 1]; n[i++] = (*componentImg)[nextRow + u]; if(u < uextent - 1) n[i++] = (*componentImg)[nextRow + u + 1]; } // associate labels int l = (*componentImg)[v * uextent + u]; for(size_t j = 0; j < i; ++j) if(n[j]) AssociateLabel(l, n[j], &tempLabels); } // condense labels 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 == 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 < componentImg->size(); ++i) (*componentImg)[i] = condensed[tempLabels[(*componentImg)[i]].first]; }
bool BitmapPrimitiveShape::Init(bool binary, std::istream *i) { if(binary) { GfxTL::AABox< GfxTL::Vector2Df > bbox; size_t uextent, vextent; // read number of components size_t size; i->read((char *)&size, sizeof(size)); if(size) { // read bbox i->read((char *)&bbox, sizeof(bbox)); // read uextent and vextent i->read((char *)&uextent, sizeof(uextent)); i->read((char *)&vextent, sizeof(vextent)); // read every component for(size_t j = 0; j < size; ++j) { // read number of polys in component size_t numPolys; i->read((char *)&numPolys, sizeof(numPolys)); for(size_t k = 0; k < numPolys; ++k) { // read number of points in poly size_t numPoints; i->read((char *)&numPoints, sizeof(numPoints)); GfxTL::VectorXD< 2, size_t > pp; for(size_t l = 0; l < numPoints; ++l) i->read((char *)&pp, sizeof(pp)); } } } } else { GfxTL::AABox< GfxTL::Vector2Df > bbox; size_t uextent, vextent; // read number of components size_t size; (*i) >> size; if(size) { // read bbox (*i) >> bbox.Min()[0] >> bbox.Max()[0] >> bbox.Min()[1] >> bbox.Max()[1]; // read uextent and vextent (*i) >> uextent >> vextent; // read every component for(size_t j = 0; j < size; ++j) { // read number of polys in component size_t numPolys; (*i) >> numPolys; for(size_t k = 0; k < numPolys; ++k) { // read number of points in poly size_t numPoints; (*i) >> numPoints; GfxTL::VectorXD< 2, size_t > pp; for(size_t l = 0; l < numPoints; ++l) (*i) >> pp[0] >> pp[1]; } } } } return true; }
size_t BitmapPrimitiveShape::ConnectedComponent( const PointCloud &pc, float epsilon, std::shared_ptr<MiscLib::Vector< size_t > >indices, bool doFiltering, float* borderRatio ) { MiscLib::Vector< int > componentsImg; MiscLib::Vector< std::pair< int, size_t > > labels; BitmapInfo bitmapInfo; if( AllConnectedComponents( pc, epsilon, bitmapInfo, indices, componentsImg, labels, doFiltering ) <= 1 ) return 0; size_t size = indices->size(); MiscLib::Vector< size_t >::iterator begin = indices->begin(); // find the largest component size_t maxComp = 1; for(size_t i = 2; i < labels.size(); ++i) if(labels[maxComp].second < labels[i].second) maxComp = i; GfxTL::AABox< GfxTL::Vector2Df > bbox; bbox.Min() = GfxTL::Vector2Df( std::numeric_limits< float >::infinity(), std::numeric_limits< float >::infinity()); bbox.Max() = -bbox.Min(); // compute bbox and update indices size_t offset = 0; for(size_t i = 0; i < size; ++i) { if(componentsImg[bitmapInfo.bmpIdx[i]] == labels[maxComp].first) { std::swap(begin[offset], begin[i]); offset++; // update bounding box if(bbox.Min()[0] > bitmapInfo.params[i].first) bbox.Min()[0] = bitmapInfo.params[i].first; if(bbox.Max()[0] < bitmapInfo.params[i].first) bbox.Max()[0] = bitmapInfo.params[i].first; if(bbox.Min()[1] > bitmapInfo.params[i].second) bbox.Min()[1] = bitmapInfo.params[i].second; if(bbox.Max()[1] < bitmapInfo.params[i].second) bbox.Max()[1] = bitmapInfo.params[i].second; } } // ratio between border and connected-comp size should be calculated if borderRatio is a valid pointer if( borderRatio ) { int borderPixels = 0; int maxLabel = labels[maxComp].first; int row = bitmapInfo.uextent; int pos = 0; char numNeighbours = 0; int ccSize = 0; // test neightbourhood for all bitmappixels that are not marginal for( size_t v = 1; v < bitmapInfo.vextent-1; ++v ) { for( size_t u = 1; u < bitmapInfo.uextent-1; ++u ) { pos = row + u; if( componentsImg[pos] == maxLabel ) { ccSize++; numNeighbours = bitmapInfo.bitmap[pos-1] + bitmapInfo.bitmap[pos+1] + bitmapInfo.bitmap[pos-bitmapInfo.uextent-1] + bitmapInfo.bitmap[pos-bitmapInfo.uextent+1] + bitmapInfo.bitmap[pos+bitmapInfo.uextent-1] + bitmapInfo.bitmap[pos+bitmapInfo.uextent+1] + bitmapInfo.bitmap[pos-bitmapInfo.uextent] + bitmapInfo.bitmap[pos+bitmapInfo.uextent]; if( (int)numNeighbours != 8 ) ++borderPixels; } } row += bitmapInfo.uextent; } // check left/right margins row = bitmapInfo.uextent; for( size_t v = 1; v < bitmapInfo.vextent-1; ++v ) { ccSize++; if( componentsImg[row] == maxLabel ) ++borderPixels; ccSize++; if( componentsImg[row+bitmapInfo.uextent-1] == maxLabel ) ++borderPixels; row += bitmapInfo.uextent; } // check top/bottom margins row = ( bitmapInfo.vextent-1 ) * bitmapInfo.uextent; for( size_t u = 0; u < bitmapInfo.uextent; ++u ) { ccSize++; if( componentsImg[u] == maxLabel ) ++borderPixels; ccSize++; if( componentsImg[row + u] == maxLabel ) ++borderPixels; } *borderRatio = static_cast<float>( borderPixels ) / static_cast<float>( ccSize ); } m_extBbox = bbox; return offset; }
void CylinderPrimitiveShape::SetExtent( const GfxTL::AABox< GfxTL::Vector2Df > &extBbox, const MiscLib::Vector< int > &componentsImg, size_t uextent, size_t vextent, float epsilon, int label) { if(extBbox.Min()[1] * m_cylinder.Radius() <= epsilon && extBbox.Max()[1] * m_cylinder.Radius() >= 2 * M_PI * m_cylinder.Radius() - epsilon) { // component has been cut along angular direction // run from both sides to find both ends size_t row = 0, j = 0; for(; j < vextent; ++j) { bool found = false; for(size_t i = 0; i < uextent; ++i) { if(componentsImg[row + i] == label) { found = true; break; } } if(!found) break; row += uextent; } size_t maxj = j; if(maxj == vextent) // cylinder is complete { m_clip = false; return; } row = (vextent - 1) * uextent, j = 0; for(; j < vextent; ++j) { bool found = false; for(size_t i = 0; i < uextent; ++i) { if(componentsImg[row + i] == label) { found = true; break; } } if(!found) break; row -= uextent; } size_t minj = j; // convert min and max to angular parameters m_minPhi = minj * epsilon / m_cylinder.Radius() + extBbox.Min()[1]; m_maxPhi = maxj * epsilon / m_cylinder.Radius() + extBbox.Min()[1]; } else { m_minPhi = extBbox.Min()[1]; m_maxPhi = extBbox.Max()[1]; } m_clip = true; }