void PlanePrimitiveShape::InBitmap(const std::pair< float, float > &param,
	float epsilon, const GfxTL::AABox< GfxTL::Vector2Df > &bbox, size_t,
	size_t, std::pair< int, int > *inBmp) const
{
	inBmp->first = (int)std::floor((param.first - bbox.Min()[0]) / epsilon);
	inBmp->second = (int)std::floor((param.second - bbox.Min()[1]) / epsilon);
}
void ConePrimitiveShape::InBitmap(const std::pair< float, float > &param,
	float epsilon, const GfxTL::AABox< GfxTL::Vector2Df > &bbox,
	size_t uextent, size_t vextent, std::pair< int, int > *inBmp) const
{
	// convert u = length and v = arc length into bitmap coordinates
	inBmp->first = std::floor((param.first - bbox.Min()[0]) / epsilon);
	inBmp->second = std::floor((param.second - bbox.Min()[1]) / epsilon);
}
bool PlanePrimitiveShape::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
{
	*p = Vec3f(((bbox.Min()[0] + epsilon * (float(u) + .5f)) * m_hcs[0] +
		(bbox.Min()[1] + epsilon * (float(v) + .5f)) * m_hcs[1]).Data()) +
		m_plane.getPosition();
	*n = m_plane.getNormal();
	return true;
}
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;
}
bool CylinderPrimitiveShape::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
{
	GfxTL::Quaternion< float > q;
	q.RotationRad((bbox.Min()[1] + epsilon * (v + .5f)) / m_cylinder.Radius(),
		m_cylinder.AxisDirection()[0],
		m_cylinder.AxisDirection()[1],
		m_cylinder.AxisDirection()[2]);
	Vec3f vvec;
	q.Rotate(m_cylinder.AngularDirection(), &vvec);
	*p = (bbox.Min()[0] + epsilon * (u + .5f)) * m_cylinder.AxisDirection() +
		m_cylinder.Radius() * vvec + m_cylinder.AxisPosition();
	*n = vvec;
	return true;
}
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];
}
Exemple #10
0
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;
}
Exemple #11
0
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;
}