コード例 #1
0
ファイル: GeneralPolygon.cpp プロジェクト: 675492062/NavMesh
std::vector<PolygonAdjacency> GeneralPolygon::_getConexions(TPPLPoly& A, TPPLPoly& B)
{
	std::vector<sf::Vector2f> pointsA = _getPoints(A);
	std::vector<sf::Vector2f> edgesA = _getPoints(A);

	std::vector<sf::Vector2f> pointsB = _getPoints(B);
	std::vector<sf::Vector2f> edgesB = _getPoints(B);

	auto dot = [&](const sf::Vector2f& a, const sf::Vector2f& b) -> float
	{
		return (a.x*b.x + a.y*b.y);
	};
	auto norm = [&](const sf::Vector2f& a) -> float
	{
		return sqrt(a.x*a.x + a.y*a.y);
	};
	auto dist = [&](const sf::Vector2f& a, const sf::Vector2f& b) -> float
	{
		float aux1 = a.x-b.x;
		float aux2 = a.y-b.y;
		return sqrt(aux1*aux1 + aux2*aux2);
	};
	auto normalized = [&](const sf::Vector2f& a) -> sf::Vector2f
	{
		float mag = norm(a);
		return (a/mag);
	};

	auto areEdgesParallel = [&](const sf::Vector2f& e1, const sf::Vector2f& e2) -> bool
	{
		if( abs( dot(normalized(e1),normalized(e2)) ) > 0.9f )
			return true;
	};

	auto minDistanceEdges = [&](const std::pair<sf::Vector2f, sf::Vector2f> &S1, const std::pair<sf::Vector2f, sf::Vector2f> &S2) -> float
	{
		// http://geomalgorithms.com/a07-_distance.html

		sf::Vector2f   u = S1.second - S1.first;
		sf::Vector2f   v = S2.second - S2.first;
		sf::Vector2f   w = S1.first - S2.first;
		float    a = dot(u,u);         // always >= 0
		float    b = dot(u,v);
		float    c = dot(v,v);         // always >= 0
		float    d = dot(u,w);
		float    e = dot(v,w);
		float    D = a*c - b*b;        // always >= 0
		float    sc, sN, sD = D;       // sc = sN / sD, default sD = D >= 0
		float    tc, tN, tD = D;       // tc = tN / tD, default tD = D >= 0

		// compute the line parameters of the two closest points
		if (D < SMALL_NUM)
		{					// the lines are almost parallel
			sN = 0.0;       // force using point P0 on segment S1
			sD = 1.0;       // to prevent possible division by 0.0 later
			tN = e;
			tD = c;
		}
		else // get the closest points on the infinite lines
		{                 
			sN = (b*e - c*d);
			tN = (a*e - b*d);
			if (sN < 0.0) // sc < 0 => the s=0 edge is visible
			{        
				sN = 0.0;
				tN = e;
				tD = c;
			}
			else if (sN > sD) // sc > 1  => the s=1 edge is visible
			{  
				sN = sD;
				tN = e + b;
				tD = c;
			}
		}

		if (tN < 0.0)
		{            // tc < 0 => the t=0 edge is visible
			tN = 0.0;
			// recompute sc for this edge
			if (-d < 0.0)
				sN = 0.0;
			else if (-d > a)
				sN = sD;
			else
			{
				sN = -d;
				sD = a;
			}
		}
		else if (tN > tD)
		{      // tc > 1  => the t=1 edge is visible
			tN = tD;
			// recompute sc for this edge
			if ((-d + b) < 0.0)
				sN = 0;
			else if ((-d + b) > a)
				sN = sD;
			else
			{
				sN = (-d +  b);
				sD = a;
			}
		}
		// finally do the division to get sc and tc
		sc = (abs(sN) < SMALL_NUM ? 0.0 : sN / sD);
		tc = (abs(tN) < SMALL_NUM ? 0.0 : tN / tD);

		// get the difference of the two closest points
		sf::Vector2f   dP = w + (sc * u) - (tc * v);  // =  S1(sc) - S2(tc)

		return norm(dP);   // return the closest distance
	};

	auto testCloseEdgePoints = [&](std::pair<sf::Vector2f, sf::Vector2f> &edgePoints1, std::pair<sf::Vector2f, sf::Vector2f> &edgePoints2, float minDist) -> bool
	{
		if( ( dist(edgePoints1.first, edgePoints2.first) < minDist ) && ( dist(edgePoints1.second, edgePoints2.second) < minDist ) )
			return true;
		if( ( dist(edgePoints1.second, edgePoints2.first) < minDist ) && ( dist(edgePoints1.first, edgePoints2.second) < minDist ) )
			return true;
		return false;
	};

	std::vector<PolygonAdjacency> conexions;


	// here the actual work
	for(unsigned int eA=0; eA < edgesA.size() ; ++eA )
		for(unsigned int eB=0; eB < edgesB.size() ; ++eB )
		{
			if( areEdgesParallel(edgesA[eA], edgesB[eB]) )
				if( minDistanceEdges(_getEdgePoints(eA, pointsA), _getEdgePoints(eB, pointsB)) < ADJACENT_DISTANCE )
					if( testCloseEdgePoints(_getEdgePoints(eA, pointsA), _getEdgePoints(eB, pointsB), ADJACENT_DISTANCE ) )
						conexions.push_back( PolygonAdjacency(&A, &B, eA, eB) );
						
		}

	return conexions;
}
コード例 #2
0
void Normals::ComputeNormals(const PolygonalModel& objs, std::vector<Normals::PolygonNormalData>& polygonNormals, NormalList& vertexNormals, PolygonAdjacencyGraph& polygonAdjacency, NormalsGeneration src)
{
	polygonNormals.clear();
	vertexNormals.clear();
	if (objs.empty())
	{
		return;
	}
	std::vector<double> polygonAreas;
	const size_t approxNumPolygons = objs.front().polygons.size() * objs.size();
	polygonAreas.reserve(approxNumPolygons);
	polygonNormals.reserve(approxNumPolygons);
	const size_t approxNumVertices = approxNumPolygons * (objs.front().polygons.empty() ? 1 : objs.front().polygons.front().points.size());
	std::unordered_map<Point3D, Vector3D, HashAndComparePoint3D, HashAndComparePoint3D> vertexMap;
	vertexMap.reserve(approxNumVertices);

	std::unordered_map<LineSegment, PolygonAdjacency, HashAndCompareEdge, HashAndCompareEdge> edgeMap;
	edgeMap.reserve(2 * approxNumVertices);

	int polygonIdx = 0;
	for (auto i = objs.begin(); i != objs.end(); ++i)
	{
		for (auto j = i->polygons.begin(); j != i->polygons.end(); ++j)
		{
			const std::pair<double, HomogeneousPoint> areaAndCentroid = j->AreaAndCentroid();
			Vector3D currPolygonNormal = j->Normal();
			if (src == NORMALS_SMART)
			{
				FixNormal(*i, j - i->polygons.begin(), areaAndCentroid, currPolygonNormal);
			}

			PolygonNormalData d(LineSegment(areaAndCentroid.second, HomogeneousPoint(Point3D(areaAndCentroid.second) + currPolygonNormal)));
			polygonNormals.push_back(d);

			polygonAreas.push_back(areaAndCentroid.first);
			for (auto v = j->points.begin(); v != j->points.end(); ++v)
			{
				if ((src != NORMALS_FILE) || j->tmpNormals.empty())
				{
					if (vertexMap.find(Point3D(*v)) == vertexMap.end())
					{
						vertexMap[Point3D(*v)] = currPolygonNormal * areaAndCentroid.first;
					}
					else
					{
						vertexMap[Point3D(*v)] += currPolygonNormal * areaAndCentroid.first;
					}
				}
				else
				{
					vertexMap[Point3D(*v)] = j->tmpNormals[v - j->points.begin()];
				}

				const LineSegment currEdge(*v, (v + 1 != j->points.end()) ? *(v + 1) : j->points.front());
				if (edgeMap.find(currEdge) == edgeMap.end())
				{
					edgeMap[currEdge] = PolygonAdjacency(polygonIdx, (i - objs.begin()), (j - i->polygons.begin()), v - j->points.begin());
				}
				else
				{
					edgeMap[currEdge].polygonIdxs.push_back(polygonIdx);
				}
			}
			++polygonIdx;
		}
	}

	polygonAdjacency.clear();
	polygonAdjacency.reserve(edgeMap.size());
	for (auto e = edgeMap.begin(); e != edgeMap.end(); ++e)
	{
		polygonAdjacency.push_back(e->second);
	}

	vertexNormals.reserve(vertexMap.size());
	for (auto i = vertexMap.begin(); i != vertexMap.end(); ++i)
	{
		const Vector3D direction = i->second.Normalized();
		vertexNormals.push_back(LineSegment(HomogeneousPoint(i->first), HomogeneousPoint(i->first + direction)));
	}

	polygonIdx = 0;
	for (auto i = objs.begin(); i != objs.end(); ++i)
	{
		for (auto j = i->polygons.begin(); j != i->polygons.end(); ++j)
		{
			for (auto v = j->points.begin(); v != j->points.end(); ++v)
			{
				const Vector3D direction = vertexMap[Point3D(*v)].Normalized();
				polygonNormals[polygonIdx].VertexNormals.push_back(LineSegment(*v, HomogeneousPoint(Point3D(*v) + direction)));
			}
			++polygonIdx;
		}
	}
}