bool Foam::featurePointConformer::createSpecialisedFeaturePoint ( const extendedFeatureEdgeMesh& feMesh, const labelList& pEds, const pointFeatureEdgesTypes& pFEdgesTypes, const List<extendedFeatureEdgeMesh::edgeStatus>& allEdStat, const label ptI, DynamicList<Vb>& pts ) const { if ( !pFEdgesTypes.found(extendedFeatureEdgeMesh::EXTERNAL) || !pFEdgesTypes.found(extendedFeatureEdgeMesh::INTERNAL) ) { return false; } if ( pFEdgesTypes[extendedFeatureEdgeMesh::EXTERNAL] == 2 && pFEdgesTypes[extendedFeatureEdgeMesh::INTERNAL] == 1 && pEds.size() == 3 ) { if (debug) Info<< "nExternal == 2 && nInternal == 1" << endl; const Foam::point& featPt = feMesh.points()[ptI]; if ( Pstream::parRun() && !foamyHexMesh_.decomposition().positionOnThisProcessor(featPt) ) { return false; } label nVert = foamyHexMesh_.number_of_vertices(); const label initialNumOfPoints = pts.size(); const scalar ppDist = foamyHexMesh_.pointPairDistance(featPt); const vectorField& normals = feMesh.normals(); const labelListList& edgeNormals = feMesh.edgeNormals(); label concaveEdgeI = -1; labelList convexEdgesI(2, label(-1)); label nConvex = 0; forAll(pEds, i) { const extendedFeatureEdgeMesh::edgeStatus& eS = allEdStat[i]; if (eS == extendedFeatureEdgeMesh::INTERNAL) { concaveEdgeI = pEds[i]; } else if (eS == extendedFeatureEdgeMesh::EXTERNAL) { convexEdgesI[nConvex++] = pEds[i]; } else if (eS == extendedFeatureEdgeMesh::FLAT) { WarningIn("Foam::conformalVoronoiMesh::" "createSpecialisedFeaturePoint") << "Edge " << eS << " is flat" << endl; } else { FatalErrorIn("Foam::conformalVoronoiMesh::" "createSpecialisedFeaturePoint") << "Edge " << eS << " not concave/convex" << exit(FatalError); } } const vector& concaveEdgePlaneANormal = normals[edgeNormals[concaveEdgeI][0]]; const vector& concaveEdgePlaneBNormal = normals[edgeNormals[concaveEdgeI][1]]; // Intersect planes parallel to the concave edge planes offset // by ppDist and the plane defined by featPt and the edge vector. plane planeA ( featPt + ppDist*concaveEdgePlaneANormal, concaveEdgePlaneANormal ); plane planeB ( featPt + ppDist*concaveEdgePlaneBNormal, concaveEdgePlaneBNormal ); const vector& concaveEdgeDir = feMesh.edgeDirection ( concaveEdgeI, ptI ); // Todo,needed later but want to get rid of this. const Foam::point concaveEdgeLocalFeatPt = featPt + ppDist*concaveEdgeDir; // Finding the nearest point on the intersecting line to the edge // point. Floating point errors often occur using planePlaneIntersect plane planeF(concaveEdgeLocalFeatPt, concaveEdgeDir); const Foam::point concaveEdgeExternalPt = planeF.planePlaneIntersect ( planeA, planeB ); // Redefine planes to be on the feature surfaces to project through planeA = plane(featPt, concaveEdgePlaneANormal); planeB = plane(featPt, concaveEdgePlaneBNormal); const Foam::point internalPtA = concaveEdgeExternalPt - 2.0*planeA.distance(concaveEdgeExternalPt) *concaveEdgePlaneANormal; pts.append ( Vb ( internalPtA, foamyHexMesh_.vertexCount() + pts.size(), Vb::vtInternalFeaturePoint, Pstream::myProcNo() ) ); const label internalPtAIndex(pts.last().index()); const Foam::point internalPtB = concaveEdgeExternalPt - 2.0*planeB.distance(concaveEdgeExternalPt) *concaveEdgePlaneBNormal; pts.append ( Vb ( internalPtB, foamyHexMesh_.vertexCount() + pts.size(), Vb::vtInternalFeaturePoint, Pstream::myProcNo() ) ); const label internalPtBIndex(pts.last().index()); // Add the external points Foam::point externalPtD; Foam::point externalPtE; vector convexEdgePlaneCNormal(vector::zero); vector convexEdgePlaneDNormal(vector::zero); const labelList& concaveEdgeNormals = edgeNormals[concaveEdgeI]; const labelList& convexEdgeANormals = edgeNormals[convexEdgesI[0]]; const labelList& convexEdgeBNormals = edgeNormals[convexEdgesI[1]]; forAll(concaveEdgeNormals, edgeNormalI) { bool convexEdgeA = false; bool convexEdgeB = false; forAll(convexEdgeANormals, edgeAnormalI) { const vector& concaveNormal = normals[concaveEdgeNormals[edgeNormalI]]; const vector& convexNormal = normals[convexEdgeANormals[edgeAnormalI]]; if (debug) { Info<< "Angle between vectors = " << degAngleBetween(concaveNormal, convexNormal) << endl; } // Need a looser tolerance, because sometimes adjacent triangles // on the same surface will be slightly out of alignment. if (areParallel(concaveNormal, convexNormal, tolParallel)) { convexEdgeA = true; } } forAll(convexEdgeBNormals, edgeBnormalI) { const vector& concaveNormal = normals[concaveEdgeNormals[edgeNormalI]]; const vector& convexNormal = normals[convexEdgeBNormals[edgeBnormalI]]; if (debug) { Info<< "Angle between vectors = " << degAngleBetween(concaveNormal, convexNormal) << endl; } // Need a looser tolerance, because sometimes adjacent triangles // on the same surface will be slightly out of alignment. if (areParallel(concaveNormal, convexNormal, tolParallel)) { convexEdgeB = true; } } if ((convexEdgeA && convexEdgeB) || (!convexEdgeA && !convexEdgeB)) { WarningIn ( "Foam::conformalVoronoiMesh" "::createSpecialisedFeaturePoint" ) << "Both or neither of the convex edges share the concave " << "edge's normal." << " convexEdgeA = " << convexEdgeA << " convexEdgeB = " << convexEdgeB << endl; // Remove points that have just been added before returning for (label i = 0; i < 2; ++i) { pts.remove(); nVert--; } return false; } if (convexEdgeA) { forAll(convexEdgeANormals, edgeAnormalI) { const vector& concaveNormal = normals[concaveEdgeNormals[edgeNormalI]]; const vector& convexNormal = normals[convexEdgeANormals[edgeAnormalI]]; if ( !areParallel(concaveNormal, convexNormal, tolParallel) ) { convexEdgePlaneCNormal = convexNormal; plane planeC(featPt, convexEdgePlaneCNormal); externalPtD = internalPtA + 2.0*planeC.distance(internalPtA) *convexEdgePlaneCNormal; pts.append ( Vb ( externalPtD, foamyHexMesh_.vertexCount() + pts.size(), Vb::vtExternalFeaturePoint, Pstream::myProcNo() ) ); ftPtPairs_.addPointPair ( internalPtAIndex, pts.last().index() ); } } } if (convexEdgeB) { forAll(convexEdgeBNormals, edgeBnormalI) { const vector& concaveNormal = normals[concaveEdgeNormals[edgeNormalI]]; const vector& convexNormal = normals[convexEdgeBNormals[edgeBnormalI]]; if ( !areParallel(concaveNormal, convexNormal, tolParallel) ) { convexEdgePlaneDNormal = convexNormal; plane planeD(featPt, convexEdgePlaneDNormal); externalPtE = internalPtB + 2.0*planeD.distance(internalPtB) *convexEdgePlaneDNormal; pts.append ( Vb ( externalPtE, foamyHexMesh_.vertexCount() + pts.size(), Vb::vtExternalFeaturePoint, Pstream::myProcNo() ) ); ftPtPairs_.addPointPair ( internalPtBIndex, pts.last().index() ); } } } } pts.append ( Vb ( concaveEdgeExternalPt, foamyHexMesh_.vertexCount() + pts.size(), Vb::vtExternalFeaturePoint, Pstream::myProcNo() ) ); ftPtPairs_.addPointPair ( internalPtBIndex, pts.last().index() ); ftPtPairs_.addPointPair ( internalPtAIndex, pts.last().index() ); const label concaveEdgeExternalPtIndex(pts.last().index()); const scalar totalAngle = radToDeg ( constant::mathematical::pi + radAngleBetween(concaveEdgePlaneANormal, concaveEdgePlaneBNormal) ); if (totalAngle > foamyHexMeshControls_.maxQuadAngle()) { // Add additional mitreing points //scalar angleSign = 1.0; vector convexEdgesPlaneNormal = 0.5*(convexEdgePlaneCNormal + convexEdgePlaneDNormal); plane planeM(featPt, convexEdgesPlaneNormal); // if // ( // geometryToConformTo_.outside // ( // featPt - convexEdgesPlaneNormal*ppDist // ) // ) // { // angleSign = -1.0; // } // scalar phi = // angleSign*acos(concaveEdgeDir & -convexEdgesPlaneNormal); // // scalar guard = // ( // 1.0 + sin(phi)*ppDist/mag // ( // concaveEdgeLocalFeatPt - concaveEdgeExternalPt // ) // )/cos(phi) - 1.0; const Foam::point internalPtF = concaveEdgeExternalPt //+ (2.0 + guard)*(concaveEdgeLocalFeatPt - concaveEdgeExternalPt); + 2.0*(concaveEdgeLocalFeatPt - concaveEdgeExternalPt); pts.append ( Vb ( internalPtF, foamyHexMesh_.vertexCount() + pts.size(), Vb::vtInternalFeaturePoint, Pstream::myProcNo() ) ); const label internalPtFIndex(pts.last().index()); ftPtPairs_.addPointPair ( concaveEdgeExternalPtIndex, pts.last().index() ); const Foam::point externalPtG = internalPtF + 2.0*planeM.distance(internalPtF)*convexEdgesPlaneNormal; pts.append ( Vb ( externalPtG, foamyHexMesh_.vertexCount() + pts.size(), Vb::vtExternalFeaturePoint, Pstream::myProcNo() ) ); ftPtPairs_.addPointPair ( internalPtFIndex, pts.last().index() ); } if (debug) { for (label ptI = initialNumOfPoints; ptI < pts.size(); ++ptI) { Info<< "Point " << ptI << " : "; meshTools::writeOBJ(Info, topoint(pts[ptI].point())); } } return true; }
void Foam::featurePointConformer::createMasterAndSlavePoints ( const extendedFeatureEdgeMesh& feMesh, const label ptI, DynamicList<Vb>& pts ) const { typedef DynamicList<autoPtr<plane> > planeDynList; typedef indexedVertexEnum::vertexType vertexType; typedef extendedFeatureEdgeMesh::edgeStatus edgeStatus; const Foam::point& featPt = feMesh.points()[ptI]; if ( ( Pstream::parRun() && !foamyHexMesh_.decomposition().positionOnThisProcessor(featPt) ) || geometryToConformTo_.outside(featPt) ) { return; } const scalar ppDist = foamyHexMesh_.pointPairDistance(featPt); // Maintain a list of master points and the planes to relect them in DynamicList<Foam::point> masterPoints; DynamicList<vertexType> masterPointsTypes; Map<planeDynList> masterPointReflections; const labelList& featPtEdges = feMesh.featurePointEdges()[ptI]; pointFeatureEdgesTypes pointEdgeTypes(feMesh, ptI); const List<extendedFeatureEdgeMesh::edgeStatus> allEdStat = pointEdgeTypes.calcPointFeatureEdgesTypes(); // Info<< nl << featPt << " " << pointEdgeTypes; const_circulator<labelList> circ(featPtEdges); // Loop around the edges of the feature point if (circ.size()) do { // const edgeStatus eStatusPrev = feMesh.getEdgeStatus(circ.prev()); const edgeStatus eStatusCurr = feMesh.getEdgeStatus(circ()); // const edgeStatus eStatusNext = feMesh.getEdgeStatus(circ.next()); // Info<< " Prev = " // << extendedFeatureEdgeMesh::edgeStatusNames_[eStatusPrev] // << " Curr = " // << extendedFeatureEdgeMesh::edgeStatusNames_[eStatusCurr] //// << " Next = " //// << extendedFeatureEdgeMesh::edgeStatusNames_[eStatusNext] // << endl; // Get the direction in which to move the point in relation to the // feature point label sign = getSign(eStatusCurr); const vector n = sharedFaceNormal(feMesh, circ(), circ.next()); const vector pointMotionDirection = sign*0.5*ppDist*n; // Info<< " Shared face normal = " << n << endl; // Info<< " Direction to move point = " << pointMotionDirection // << endl; if (masterPoints.empty()) { // Initialise with the first master point Foam::point pt = featPt + pointMotionDirection; planeDynList firstPlane; firstPlane.append(autoPtr<plane>(new plane(featPt, n))); masterPoints.append(pt); masterPointsTypes.append ( sign == 1 ? Vb::vtExternalFeaturePoint // true : Vb::vtInternalFeaturePoint // false ); //Info<< " " << " " << firstPlane << endl; // const Foam::point reflectedPoint = reflectPointInPlane // ( // masterPoints.last(), // firstPlane.last()() // ); masterPointReflections.insert ( masterPoints.size() - 1, firstPlane ); } // else if // ( // eStatusPrev == extendedFeatureEdgeMesh::INTERNAL // && eStatusCurr == extendedFeatureEdgeMesh::EXTERNAL // ) // { // // Insert a new master point. // Foam::point pt = featPt + pointMotionDirection; // // planeDynList firstPlane; // firstPlane.append(autoPtr<plane>(new plane(featPt, n))); // // masterPoints.append(pt); // // masterPointsTypes.append // ( // sign == 1 // ? Vb::vtExternalFeaturePoint // true // : Vb::vtInternalFeaturePoint // false // ); // // masterPointReflections.insert // ( // masterPoints.size() - 1, // firstPlane // ); // } // else if // ( // eStatusPrev == extendedFeatureEdgeMesh::EXTERNAL // && eStatusCurr == extendedFeatureEdgeMesh::INTERNAL // ) // { // // } else { // Just add this face contribution to the latest master point masterPoints.last() += pointMotionDirection; masterPointReflections[masterPoints.size() - 1].append ( autoPtr<plane>(new plane(featPt, n)) ); } } while (circ.circulate(CirculatorBase::CLOCKWISE)); addMasterAndSlavePoints ( masterPoints, masterPointsTypes, masterPointReflections, pts, ptI ); }