void FixBoarderNormals( surface_points_t *sp ) { int u, v; vec3d_t tmp; for ( u = 0; u < sp->upointnum; u++ ) { GetSurfacePoint( sp, u, 0, tmp ); FixNormal( tmp, tmp ); SetSurfacePoint( sp, u, 0, tmp ); GetSurfacePoint( sp, u, sp->vpointnum-1, tmp ); FixNormal( tmp, tmp ); SetSurfacePoint( sp, u, sp->vpointnum-1, tmp ); } for ( v = 0; v < sp->vpointnum; v++ ) { GetSurfacePoint( sp, 0, v, tmp ); FixNormal( tmp, tmp ); SetSurfacePoint( sp, 0, v, tmp ); GetSurfacePoint( sp, sp->upointnum-1, v, tmp ); FixNormal( tmp, tmp ); SetSurfacePoint( sp, sp->upointnum-1, v, tmp ); } }
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; } } }