- static const int aNbFeatures = 2;
- FeaturePtr aFeature[aNbFeatures] = {theFeatureA, theFeatureB};
- std::shared_ptr<GeomAPI_XY> aStart[aNbFeatures], aEnd[aNbFeatures], aCenter[aNbFeatures];
- std::shared_ptr<GeomDataAPI_Point2D> aStartPoint, aEndPoint;
-
- for (int i = 0; i < aNbFeatures; i++) {
- if (aFeature[i]->getKind() == SketchPlugin_Line::ID()) {
- aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aFeature[i]->attribute(SketchPlugin_Line::START_ID()));
- aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aFeature[i]->attribute(SketchPlugin_Line::END_ID()));
- } else if (aFeature[i]->getKind() == SketchPlugin_Arc::ID()) {
- aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aFeature[i]->attribute(SketchPlugin_Arc::START_ID()));
- aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aFeature[i]->attribute(SketchPlugin_Arc::END_ID()));
- aCenter[i] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aFeature[i]->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt()->xy();
- } else
- return;
- aStart[i] = std::shared_ptr<GeomAPI_XY>(theNotInversed[i] ?
- new GeomAPI_XY(aStartPoint->x(), aStartPoint->y()) :
- new GeomAPI_XY(aEndPoint->x(), aEndPoint->y()));
- aEnd[i] = std::shared_ptr<GeomAPI_XY>(theNotInversed[i] ?
- new GeomAPI_XY(aEndPoint->x(), aEndPoint->y()) :
- new GeomAPI_XY(aStartPoint->x(), aStartPoint->y()));
- }
-
- if (theFeatureA->getKind() == SketchPlugin_Line::ID() &&
- theFeatureB->getKind() == SketchPlugin_Line::ID()) {
- std::shared_ptr<GeomAPI_Dir2d> aDir[2];
- std::shared_ptr<GeomAPI_Dir2d> aDirT[2];
- for (int i = 0; i < aNbFeatures; i++) {
- aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aEnd[i]->decreased(aStart[i])));
- aDirT[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(-aDir[i]->y(), aDir[i]->x()));
- }
-
- // get and filter possible centers
- std::list< std::shared_ptr<GeomAPI_XY> > aSuspectCenters;
- possibleFilletCenterLineLine(aStart[0], aDir[0], aStart[1], aDir[1],
- theRadius, aSuspectCenters);
- double aDot = 0.0;
- std::list< std::shared_ptr<GeomAPI_XY> >::iterator anIt = aSuspectCenters.begin();
- for (; anIt != aSuspectCenters.end(); anIt++) {
- aDot = aDirT[0]->xy()->dot(aStart[0]->decreased(*anIt));
- theTangentA = (*anIt)->added(aDirT[0]->xy()->multiplied(aDot));
- if (theTangentA->decreased(aStart[0])->dot(aDir[0]->xy()) < 0.0)
- continue; // incorrect position
- aDot = aDirT[1]->xy()->dot(aStart[1]->decreased(*anIt));
- theTangentB = (*anIt)->added(aDirT[1]->xy()->multiplied(aDot));
- if (theTangentB->decreased(aStart[1])->dot(aDir[1]->xy()) < 0.0)
- continue; // incorrect position
- // the center is found, stop searching
- theCenter = *anIt;
- return;
- }
- } else if ((theFeatureA->getKind() == SketchPlugin_Arc::ID() &&
- theFeatureB->getKind() == SketchPlugin_Line::ID()) ||
- (theFeatureA->getKind() == SketchPlugin_Line::ID() &&
- theFeatureB->getKind() == SketchPlugin_Arc::ID())) {
- int aLineInd = theFeatureA->getKind() == SketchPlugin_Line::ID() ? 0 : 1;
- double anArcRadius = aStart[1-aLineInd]->distance(aCenter[1-aLineInd]);
- std::shared_ptr<GeomAPI_Dir2d> aDirLine = std::shared_ptr<GeomAPI_Dir2d>(
- new GeomAPI_Dir2d(aEnd[aLineInd]->decreased(aStart[aLineInd])));
- std::shared_ptr<GeomAPI_Dir2d> aDirT = std::shared_ptr<GeomAPI_Dir2d>(
- new GeomAPI_Dir2d(-aDirLine->y(), aDirLine->x()));
-
- std::shared_ptr<GeomAPI_Dir2d> aStartArcDir = std::shared_ptr<GeomAPI_Dir2d>(
- new GeomAPI_Dir2d(aStart[1-aLineInd]->decreased(aCenter[1-aLineInd])));
- std::shared_ptr<GeomAPI_Dir2d> aEndArcDir = std::shared_ptr<GeomAPI_Dir2d>(
- new GeomAPI_Dir2d(aEnd[1-aLineInd]->decreased(aCenter[1-aLineInd])));
- double anArcAngle = aStartArcDir->angle(aEndArcDir);
- if (anArcAngle < 0.0)
- anArcAngle += 2.0 * PI;
-
- // get possible centers and filter them
- std::list< std::shared_ptr<GeomAPI_XY> > aSuspectCenters;
- possibleFilletCenterLineArc(aStart[aLineInd], aDirLine, aCenter[1-aLineInd],
- anArcRadius, theRadius, aSuspectCenters);
- double aDot = 0.0;
- // the line is forward into the arc
- double innerArc = aCenter[1-aLineInd]->decreased(aStart[aLineInd])->dot(aDirLine->xy());
- std::shared_ptr<GeomAPI_XY> aLineTgPoint, anArcTgPoint;
- // The possible centers are ranged by their positions.
- // If the point is not satisfy one of criteria, the weight is decreased with penalty.
- int aBestWeight = 0;
- std::list< std::shared_ptr<GeomAPI_XY> >::iterator anIt = aSuspectCenters.begin();
- for (; anIt != aSuspectCenters.end(); anIt++) {
- int aWeight = 2;
- aDot = aDirT->xy()->dot(aStart[aLineInd]->decreased(*anIt));
- aLineTgPoint = (*anIt)->added(aDirT->xy()->multiplied(aDot));
- // Check the point is placed on the correct arc (penalty if false)
- if (aCenter[1-aLineInd]->distance(*anIt) * innerArc > anArcRadius * innerArc)
- aWeight -= 1;
- std::shared_ptr<GeomAPI_Dir2d> aCurDir = std::shared_ptr<GeomAPI_Dir2d>(
- new GeomAPI_Dir2d((*anIt)->decreased(aCenter[1-aLineInd])));
- double aCurAngle = aStartArcDir->angle(aCurDir);
- if (aCurAngle < 0.0)
- aCurAngle += 2.0 * PI;
- if (aCurAngle < 0.0 || aCurAngle > anArcAngle)
- continue;
- if (aWeight > aBestWeight)
- aBestWeight = aWeight;
- else if (aWeight < aBestWeight ||
- aStart[aLineInd]->distance(*anIt) >
- aStart[aLineInd]->distance(theCenter)) // <-- take closer point
- continue;
- // the center is found, stop searching
- theCenter = *anIt;
- anArcTgPoint = aCenter[1-aLineInd]->added(aCurDir->xy()->multiplied(anArcRadius));
- if (theFeatureA->getKind() == SketchPlugin_Line::ID()) {
- theTangentA = aLineTgPoint;
- theTangentB = anArcTgPoint;
- } else {
- theTangentA = anArcTgPoint;
- theTangentB = aLineTgPoint;
- }
- //return;
- }
- } else if (theFeatureA->getKind() == SketchPlugin_Arc::ID() &&
- theFeatureB->getKind() == SketchPlugin_Arc::ID()) {
- double anArcRadius[aNbFeatures];
- double anArcAngle[aNbFeatures];
- std::shared_ptr<GeomAPI_Dir2d> aStartArcDir[aNbFeatures];
- for (int i = 0; i < aNbFeatures; i++) {
- anArcRadius[i] = aStart[i]->distance(aCenter[i]);
- aStartArcDir[i] = std::shared_ptr<GeomAPI_Dir2d>(
- new GeomAPI_Dir2d(aStart[i]->decreased(aCenter[i])));
- std::shared_ptr<GeomAPI_Dir2d> aEndArcDir = std::shared_ptr<GeomAPI_Dir2d>(
- new GeomAPI_Dir2d(aEnd[i]->decreased(aCenter[i])));
- anArcAngle[i] = aStartArcDir[i]->angle(aEndArcDir);
- if (anArcAngle[i] < 0.0)
- anArcAngle[i] += 2.0 * PI;
- }
-
- // get and filter possible centers
- std::list< std::shared_ptr<GeomAPI_XY> > aSuspectCenters;
- possibleFilletCenterArcArc(aCenter[0], anArcRadius[0], aCenter[1],
- anArcRadius[1], theRadius, aSuspectCenters);
- double aDot = 0.0;
- std::shared_ptr<GeomAPI_XY> aLineTgPoint, anArcTgPoint;
- std::list< std::shared_ptr<GeomAPI_XY> >::iterator anIt = aSuspectCenters.begin();
- for (; anIt != aSuspectCenters.end(); anIt++) {
- std::shared_ptr<GeomAPI_Dir2d> aCurDir = std::shared_ptr<GeomAPI_Dir2d>(
- new GeomAPI_Dir2d((*anIt)->decreased(aCenter[0])));
- double aCurAngle = aStartArcDir[0]->angle(aCurDir);
- if (aCurAngle < 0.0)
- aCurAngle += 2.0 * PI;
- if (aCurAngle < 0.0 || aCurAngle > anArcAngle[0])
- continue; // incorrect position
- theTangentA = aCenter[0]->added(aCurDir->xy()->multiplied(anArcRadius[0]));
-
- aCurDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d((*anIt)->decreased(aCenter[1])));
- aCurAngle = aStartArcDir[1]->angle(aCurDir);
- if (aCurAngle < 0.0)
- aCurAngle += 2.0 * PI;
- if (aCurAngle < 0.0 || aCurAngle > anArcAngle[1])
- continue; // incorrect position
- theTangentB = aCenter[1]->added(aCurDir->xy()->multiplied(anArcRadius[1]));
-
- // the center is found, stop searching
- theCenter = *anIt;
- return;