Salome HOME
Update projected coordinate axes when changing one coordinate plane to another.
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_Sketch.cpp
index 2f51ae2da3a07731069f59eb9d846f0d344798a8..0daeb330d810e76a3eea6ac3d964764e15bc607e 100644 (file)
 #include <Config_PropManager.h>
 
 #include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_EdgeBuilder.h>
 #include <GeomAlgoAPI_FaceBuilder.h>
 
 #include <GeomAPI_Dir.h>
+#include <GeomAPI_Lin.h>
 #include <GeomAPI_PlanarEdges.h>
 #include <GeomAPI_ShapeIterator.h>
 #include <GeomAPI_Vertex.h>
@@ -249,6 +251,35 @@ bool SketchPlugin_Sketch::isSub(ObjectPtr theObject) const
 }
 
 
+static bool isOrigin(const GeomPointPtr& thePoint, const double theTolerance)
+{
+  return fabs(thePoint->x()) < theTolerance &&
+         fabs(thePoint->y()) < theTolerance &&
+         fabs(thePoint->z()) < theTolerance;
+}
+
+static bool isCoordinateAxis(const GeomDirPtr& theDir, const double theTolerance)
+{
+  return fabs(theDir->x() - 1.0) < theTolerance || fabs(theDir->x() + 1.0) < theTolerance ||
+         fabs(theDir->y() - 1.0) < theTolerance || fabs(theDir->y() + 1.0) < theTolerance ||
+         fabs(theDir->z() - 1.0) < theTolerance || fabs(theDir->z() + 1.0) < theTolerance;
+}
+
+static bool isCoordinatePlane(const GeomAx3Ptr& thePlane)
+{
+  static const double THE_TOLERANCE = 1.e-7;
+  if (!thePlane)
+    return false;
+
+  GeomPointPtr anOrigin = thePlane->origin();
+  GeomDirPtr aNormal = thePlane->normal();
+  GeomDirPtr aDirX = thePlane->dirX();
+
+  return isOrigin(anOrigin, THE_TOLERANCE) &&
+         isCoordinateAxis(aNormal, THE_TOLERANCE) &&
+         isCoordinateAxis(aDirX, THE_TOLERANCE);
+}
+
 void SketchPlugin_Sketch::attributeChanged(const std::string& theID) {
   if (theID == SketchPlugin_SketchEntity::EXTERNAL_ID()) {
     AttributeSelectionPtr aSelAttr = selection(SketchPlugin_SketchEntity::EXTERNAL_ID());
@@ -299,14 +330,28 @@ void SketchPlugin_Sketch::attributeChanged(const std::string& theID) {
       }
     }
   } else if (theID == NORM_ID() || theID == DIRX_ID() || theID == ORIGIN_ID()) {
+    // check if current and previous sketch planes are coordinate planes and they are different
+    GeomAx3Ptr aCurPlane;
+    bool areCoordPlanes = false;
+    if (isPlaneSet()) {
+      aCurPlane = coordinatePlane();
+      areCoordPlanes = isCoordinatePlane(aCurPlane) && isCoordinatePlane(myPlane);
+    }
+
     // send all sub-elements are also updated: all entities become created on different plane
     static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
     std::list<ObjectPtr> aSubs = data()->reflist(SketchPlugin_Sketch::FEATURES_ID())->list();
     std::list<ObjectPtr>::iterator aSub = aSubs.begin();
     for(; aSub != aSubs.end(); aSub++) {
-      if (aSub->get())
+      if (aSub->get()) {
+        if (areCoordPlanes)
+          updateCoordinateAxis(*aSub, aCurPlane);
+
         ModelAPI_EventCreator::get()->sendUpdated(*aSub, anUpdateEvent);
+      }
     }
+    if (aCurPlane)
+      myPlane = aCurPlane;
   }
 }
 
@@ -433,3 +478,95 @@ bool SketchPlugin_Sketch::removeLinksToExternal()
     document()->removeFeature(*anIt);
   return true;
 }
+
+
+static ObjectPtr findAxis(GeomShapePtr theAxisToCompare,
+                          ObjectPtr theOX,
+                          ObjectPtr theOY,
+                          ObjectPtr theOZ)
+{
+  if (theAxisToCompare) {
+    ObjectPtr anAxes[] = { theOX, theOY, theOZ };
+    for (int i = 0; i < 3; ++i) {
+      ResultPtr anAx = std::dynamic_pointer_cast<ModelAPI_Result>(anAxes[i]);
+      if (anAx && theAxisToCompare->isEqual(anAx->shape()))
+        return anAxes[i];
+    }
+  }
+  return ObjectPtr();
+}
+
+static ObjectPtr findAxis(ObjectPtr theAxisToCompare,
+                          ObjectPtr theOX,
+                          ObjectPtr theOY,
+                          ObjectPtr theOZ)
+{
+  if (theAxisToCompare == theOX)
+    return theOX;
+  else if (theAxisToCompare == theOY)
+    return theOY;
+  else if (theAxisToCompare == theOZ)
+    return theOZ;
+  // nothing helped, search by shape
+  ResultPtr anAxis = std::dynamic_pointer_cast<ModelAPI_Result>(theAxisToCompare);
+  return findAxis(anAxis ? anAxis->shape() : GeomShapePtr(), theOX, theOY, theOZ);
+}
+
+GeomShapePtr axisOnNewPlane(ObjectPtr theAxis, GeomAx3Ptr theOldPlane, GeomAx3Ptr theNewPlane)
+{
+  ResultPtr anAxis = std::dynamic_pointer_cast<ModelAPI_Result>(theAxis);
+  if (!anAxis)
+    return GeomShapePtr();
+
+  GeomEdgePtr anAxisEdge = anAxis->shape()->edge();
+  GeomLinePtr anAxisLine = anAxisEdge->line();
+  GeomDirPtr anAxisDir = anAxisLine->direction();
+
+  double aFirstParam, aLastParam;
+  anAxisEdge->getRange(aFirstParam, aLastParam);
+
+  if (theOldPlane->dirX()->isParallel(anAxisDir))
+    anAxisDir = theNewPlane->dirX();
+  else if (theOldPlane->dirY()->isParallel(anAxisDir))
+    anAxisDir = theNewPlane->dirY();
+  else if (theOldPlane->normal()->isParallel(anAxisDir))
+    anAxisDir = theNewPlane->normal();
+
+  GeomPointPtr aFirstPoint(new GeomAPI_Pnt(aFirstParam * anAxisDir->x(),
+                                           aFirstParam * anAxisDir->y(),
+                                           aFirstParam * anAxisDir->z()));
+  GeomPointPtr aLastPoint(new GeomAPI_Pnt(aLastParam * anAxisDir->x(),
+                                          aLastParam * anAxisDir->y(),
+                                          aLastParam * anAxisDir->z()));
+  return GeomAlgoAPI_EdgeBuilder::line(aFirstPoint, aLastPoint);
+}
+
+void  SketchPlugin_Sketch::updateCoordinateAxis(ObjectPtr theSub, GeomAx3Ptr thePlane)
+{
+  FeaturePtr aFeature = ModelAPI_Feature::feature(theSub);
+  if (!aFeature)
+    return;
+
+  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+  ObjectPtr anOX = aRootDoc->objectByName(ModelAPI_ResultConstruction::group(), "OX");
+  ObjectPtr anOY = aRootDoc->objectByName(ModelAPI_ResultConstruction::group(), "OY");
+  ObjectPtr anOZ = aRootDoc->objectByName(ModelAPI_ResultConstruction::group(), "OZ");
+
+  AttributeSelectionPtr anExtFeature;
+  if (aFeature->getKind() == SketchPlugin_Projection::ID())
+    anExtFeature = aFeature->selection(SketchPlugin_Projection::EXTERNAL_FEATURE_ID());
+  else if (aFeature->getKind() == SketchPlugin_IntersectionPoint::ID())
+    anExtFeature = aFeature->selection(SketchPlugin_IntersectionPoint::EXTERNAL_FEATURE_ID());
+  else
+    return;
+
+  ObjectPtr aContext = anExtFeature->context();
+  GeomShapePtr aShape = anExtFeature->value();
+  if (!aShape) { // selected object is a construction
+    ObjectPtr anAxis = findAxis(aContext, anOX, anOY, anOZ);
+    GeomShapePtr aNewAxis = axisOnNewPlane(anAxis, myPlane, thePlane);
+    anAxis = findAxis(aNewAxis, anOX, anOY, anOZ);
+    if (anAxis)
+      anExtFeature->setValue(anAxis, aShape);
+  }
+}