+ // Calculate directions, which comply the normal, for vertices and edges
+ if (!hasNormal[0] || !hasNormal[1]) {
+ if (hasNormal[0] || hasNormal[1]) { // plane with line or vertex
+ if (hasDirection[0] || hasDirection[1]) { // plane - line
+ int anInd = hasDirection[0] ? 0 : 1;
+ gp_Vec aVec = aSrcDstNormals[1 - anInd].Crossed(aSrcDstDirections[anInd]);
+ if (aVec.SquareMagnitude() < Precision::SquareConfusion()) {
+ // normal and direction are collinear
+ aVec = aSrcDstNormals[1 - anInd].Crossed(
+ gp_Vec(aSrcDstPoints[1 - anInd], aSrcDstPoints[anInd]));
+ if (aVec.SquareMagnitude() < Precision::SquareConfusion()) {
+ // normal and points direction are collinear
+ if (Abs(aSrcDstNormals[1 - anInd].Y()) >= Precision::Confusion() ||
+ Abs(aSrcDstNormals[1 - anInd].Z()) >= Precision::Confusion())
+ aVec = gp::DX();
+ else
+ aVec = gp::DY();
+ }
+ }
+ aSrcDstNormals[anInd] = aSrcDstDirections[anInd].Crossed(aVec).Normalized();
+ } else { // plane - point
+ int anInd = hasNormal[0] ? 1 : 0;
+ aSrcDstNormals[anInd] = aSrcDstNormals[1 - anInd];
+ }
+ } else {
+ if (hasDirection[0] && hasDirection[1]) { // line - line
+ gp_Vec aVec = aSrcDstDirections[0].Crossed(aSrcDstDirections[1]);
+ if (aVec.SquareMagnitude() < Precision::SquareConfusion()) { // lines are parallel
+ aVec = aSrcDstDirections[0].Crossed(gp_Vec(aSrcDstPoints[0], aSrcDstPoints[1]));
+ if (aVec.SquareMagnitude() < Precision::SquareConfusion()) { // lines are equal
+ if (Abs(aSrcDstDirections[0].Y()) >= Precision::Confusion() ||
+ Abs(aSrcDstDirections[0].Z()) >= Precision::Confusion())
+ aVec = gp::DX();
+ else
+ aVec = gp::DY();
+ }
+ }
+ aSrcDstNormals[0] = aSrcDstDirections[0].Crossed(aVec);
+ aSrcDstNormals[0].Normalize();
+ aSrcDstNormals[1] = aSrcDstDirections[1].Crossed(aVec);
+ aSrcDstNormals[1].Normalize();
+ if (aSrcDstDirections[0].Dot(aSrcDstDirections[1]) < -Precision::Confusion())
+ aSrcDstNormals[1].Reverse();
+ } else if (!hasDirection[0] && !hasDirection[1]) { // point - point
+ aSrcDstNormals[0] = gp_Vec(aSrcDstPoints[0], aSrcDstPoints[1]);
+ aSrcDstNormals[0].Normalize();
+ aSrcDstNormals[1] = -aSrcDstNormals[0];
+ } else { // line - point
+ int anInd = hasDirection[0] ? 0 : 1;
+ gp_Vec aVec(aSrcDstPoints[anInd], aSrcDstPoints[1 - anInd]);
+ aVec.Cross(aSrcDstDirections[anInd]);
+ if (aVec.SquareMagnitude() < Precision::SquareConfusion()) { // point is on line
+ if (Abs(aSrcDstDirections[anInd].Y()) >= Precision::Confusion() ||
+ Abs(aSrcDstDirections[anInd].Z()) >= Precision::Confusion())
+ aVec = gp::DX();
+ else
+ aVec = gp::DY();
+ }
+ aSrcDstNormals[anInd] = aSrcDstDirections[anInd].Crossed(aVec).Normalized();
+ aSrcDstNormals[1 - anInd] = aSrcDstNormals[anInd];
+ }
+ }