]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
30.10.2014. Redesigned boolean feature.
authorszy <szy@opencascade.com>
Thu, 30 Oct 2014 16:17:29 +0000 (19:17 +0300)
committerszy <szy@opencascade.com>
Thu, 30 Oct 2014 16:17:29 +0000 (19:17 +0300)
src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp
src/FeaturesPlugin/FeaturesPlugin_Boolean.h
src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp
src/GeomAlgoAPI/GeomAlgoAPI_Boolean.cpp
src/GeomAlgoAPI/GeomAlgoAPI_Boolean.h
src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.cpp
src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.h

index 3161b31c22e9cd1978659f88834d512b6ce8dc9c..e582019b4839f3d18ee494cd9ff39c0f60860873 100644 (file)
 #include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_ResultBody.h>
 #include <GeomAlgoAPI_Boolean.h>
-
+#include <Events_Error.h>
 using namespace std;
+#ifdef _DEBUG
+#include <iostream>
+#include <ostream>
+#endif
 
+#define FACE 4
+#define _MODIFY_TAG 1
+#define _DELETED_TAG 2
 FeaturesPlugin_Boolean::FeaturesPlugin_Boolean()
 {
 }
@@ -46,25 +53,61 @@ void FeaturesPlugin_Boolean::execute()
     return;
   int aType = aTypeAttr->value();
 
-  boost::shared_ptr<GeomAPI_Shape> aObject = this->getShape(FeaturesPlugin_Boolean::OBJECT_ID());
-  if (!aObject)
+  boost::shared_ptr<GeomAPI_Shape> anObject = this->getShape(FeaturesPlugin_Boolean::OBJECT_ID());
+  if (!anObject)
     return;
 
   boost::shared_ptr<GeomAPI_Shape> aTool = this->getShape(FeaturesPlugin_Boolean::TOOL_ID());
   if (!aTool)
     return;
 
-  boost::shared_ptr<ModelAPI_ResultBody> aResult = document()->createBody(data());
-  switch (aType) {
-  case BOOL_CUT:
-    aResult->store(GeomAlgoAPI_Boolean::makeCut(aObject, aTool));
-    break;
-  case BOOL_FUSE:
-    aResult->store(GeomAlgoAPI_Boolean::makeFuse(aObject, aTool));
-    break;
-  case BOOL_COMMON:
-    aResult->store(GeomAlgoAPI_Boolean::makeCommon(aObject, aTool));
-    break;
+  boost::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data());
+
+  GeomAlgoAPI_Boolean* aFeature = new GeomAlgoAPI_Boolean(anObject, aTool, aType);
+  if(aFeature && !aFeature->isDone()) {
+    std::string aFeatureError = "Boolean feature: algorithm failed";  
+    Events_Error::send(aFeatureError, this);
+    return;
   }
-  setResult(aResult);
-}
\ No newline at end of file
+   // Check if shape is valid
+  if (aFeature->shape()->isNull()) {
+    std::string aShapeError = "Boolean feature: resulting shape is Null";     
+    Events_Error::send(aShapeError, this);
+#ifdef _DEBUG
+    std::cerr << aShapeError << std::endl;
+#endif
+    return;
+  }
+  if(!aFeature->isValid()) {
+    std::string aFeatureError = "Boolean feature: resulting shape is not valid";  
+    Events_Error::send(aFeatureError, this);
+    return;
+  }  
+  //LoadNamingDS
+  LoadNamingDS(aFeature, aResultBody, anObject, aTool, aType);
+
+  setResult(aResultBody);
+}
+
+//============================================================================
+void FeaturesPlugin_Boolean::LoadNamingDS(GeomAlgoAPI_Boolean* theFeature, 
+                                               boost::shared_ptr<ModelAPI_ResultBody> theResultBody, 
+                                               boost::shared_ptr<GeomAPI_Shape> theObject,
+                                               boost::shared_ptr<GeomAPI_Shape> theTool,
+                                               int theType)
+{  
+
+  //load result
+  theResultBody->storeModified(theObject, theFeature->shape()); 
+
+  GeomAPI_DataMapOfShapeShape* aSubShapes = new GeomAPI_DataMapOfShapeShape();
+  theFeature->mapOfShapes(*aSubShapes);
+
+  // Put in DF modified faces
+  theResultBody->loadAndOrientModifiedShapes(theFeature->makeShape(), theObject, FACE, _MODIFY_TAG, *aSubShapes);
+  theResultBody->loadAndOrientModifiedShapes(theFeature->makeShape(), theTool,   FACE, _MODIFY_TAG, *aSubShapes);
+
+  //Put in DF deleted faces
+  theResultBody->loadDeletedShapes(theFeature->makeShape(), theObject, FACE, _DELETED_TAG);
+  theResultBody->loadDeletedShapes(theFeature->makeShape(), theTool,   FACE, _DELETED_TAG);  
+}
index 15916356569abc74383bae93e39195b0080e9c34..0fdeb6baeee7901f36a0b3babea4c798687c32f2 100644 (file)
@@ -8,6 +8,7 @@
 #include "FeaturesPlugin.h"
 #include <ModelAPI_Feature.h>
 #include <GeomAPI_Shape.h>
+#include <GeomAlgoAPI_Boolean.h>
 
 class FeaturesPlugin_Boolean : public ModelAPI_Feature
 {
@@ -38,8 +39,8 @@ class FeaturesPlugin_Boolean : public ModelAPI_Feature
   }
 
   enum {
-    BOOL_CUT,
     BOOL_FUSE,
+       BOOL_CUT,
     BOOL_COMMON
   };
 
@@ -62,7 +63,13 @@ class FeaturesPlugin_Boolean : public ModelAPI_Feature
 
 private:
   boost::shared_ptr<GeomAPI_Shape> getShape(const std::string& theAttrName);
-
+  
+  /// Load Naming data structure of the feature to the document
+  void LoadNamingDS(GeomAlgoAPI_Boolean* theFeature, 
+                                       boost::shared_ptr<ModelAPI_ResultBody> theResultBody,
+                       boost::shared_ptr<GeomAPI_Shape> theObject,
+                       boost::shared_ptr<GeomAPI_Shape> theTool,
+                                       int theType);
 };
 
 #endif
index 7316f3c2c644ae24b260310ae2af6071170f346f..eeafb1db61e0e7557ff59706166146f75c41b219 100644 (file)
@@ -65,7 +65,6 @@ void FeaturesPlugin_Extrusion::execute()
   if (data()->boolean(FeaturesPlugin_Extrusion::REVERSE_ID())->value())
     aSize = -aSize;
 
-  eraseResults(); // to erase the previously stored naming structures
   boost::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data());
   GeomAlgoAPI_Extrusion aFeature(aFace, aSize);
   if(!aFeature.isDone()) {
index d56a226aa8795aa529a5f865c79b6706cb2be649..e75205a02d34d3b7b903636d97f0dc99a91fe6f9 100644 (file)
@@ -7,8 +7,13 @@
 #include <BRepAlgoAPI_Cut.hxx>
 #include <BRepAlgoAPI_Common.hxx>
 #include <BRepAlgoAPI_Fuse.hxx>
+#include <BRepCheck_Analyzer.hxx>
+#include <TopExp_Explorer.hxx>
+#include <GeomAlgoAPI_DFLoader.h>
 
-
+#define  FUSE   0
+#define  CUT    1
+#define  COMMON 2
 boost::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_Boolean::makeCut(
   boost::shared_ptr<GeomAPI_Shape> theShape,
   boost::shared_ptr<GeomAPI_Shape> theTool)
@@ -57,4 +62,107 @@ boost::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_Boolean::makeCommon(
     return aResult;
   }
   return boost::shared_ptr<GeomAPI_Shape>();
+}
+
+//============================================================================
+GeomAlgoAPI_Boolean::GeomAlgoAPI_Boolean(boost::shared_ptr<GeomAPI_Shape> theObject,
+                                         boost::shared_ptr<GeomAPI_Shape> theTool,
+                                         int theType)
+: myOperation(theType), myDone(false), myShape(new GeomAPI_Shape())
+{
+  build(theObject, theTool);
+}
+
+
+//============================================================================
+void GeomAlgoAPI_Boolean::build(boost::shared_ptr<GeomAPI_Shape> theObject,
+                                boost::shared_ptr<GeomAPI_Shape> theTool)
+{
+  const TopoDS_Shape& anObject = theObject->impl<TopoDS_Shape>();
+  const TopoDS_Shape& aTool    = theTool->impl<TopoDS_Shape>();
+  TopoDS_Shape aResult;
+  switch (myOperation) {
+  case BOOL_FUSE: 
+       {
+         BRepAlgoAPI_Fuse* mkFuse = new BRepAlgoAPI_Fuse(anObject, aTool);
+      if (mkFuse && mkFuse->IsDone()) {
+               setImpl(mkFuse);
+               myDone = mkFuse->IsDone() == Standard_True;
+               myMkShape = new GeomAlgoAPI_MakeShape (mkFuse);
+               aResult = mkFuse->Shape();//GeomAlgoAPI_DFLoader::refineResult(aFuse->Shape());      
+         }
+       }
+  case BOOL_CUT:
+       {
+      BRepAlgoAPI_Cut* mkCut = new BRepAlgoAPI_Cut(anObject, aTool);
+      if (mkCut && mkCut->IsDone()) {
+               setImpl(mkCut);
+               myDone = mkCut->IsDone() == Standard_True;
+               myMkShape = new GeomAlgoAPI_MakeShape (mkCut);
+               aResult = mkCut->Shape();    
+         }
+       }
+  case BOOL_COMMON:
+       {
+      BRepAlgoAPI_Common* mkCom = new BRepAlgoAPI_Common(anObject, aTool);
+      if (mkCom && mkCom->IsDone()) {
+               setImpl(mkCom);
+               myDone = mkCom->IsDone() == Standard_True;
+               myMkShape = new GeomAlgoAPI_MakeShape (mkCom);
+               aResult = mkCom->Shape(); 
+         }
+       }       
+  }
+  if(myDone) {
+       if(aResult.ShapeType() == TopAbs_COMPOUND) 
+      aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
+       myShape->setImpl(new TopoDS_Shape(aResult));
+       boost::shared_ptr<GeomAPI_Shape> aGeomResult(new GeomAPI_Shape());
+       aGeomResult->setImpl(new TopoDS_Shape(aResult)); 
+
+       // fill data map to keep correct orientation of sub-shapes 
+       for (TopExp_Explorer Exp(aResult,TopAbs_FACE); Exp.More(); Exp.Next()) {
+         boost::shared_ptr<GeomAPI_Shape> aCurrentShape(new GeomAPI_Shape());
+      aCurrentShape->setImpl(new TopoDS_Shape(Exp.Current()));
+         myMap.bind(aCurrentShape, aCurrentShape);
+       }
+  }  
+}
+
+
+//============================================================================
+const bool GeomAlgoAPI_Boolean::isDone() const
+{return myDone;}
+
+//============================================================================
+const bool GeomAlgoAPI_Boolean::isValid() const
+{
+  BRepCheck_Analyzer aChecker(myShape->impl<TopoDS_Shape>());
+  return (aChecker.IsValid() == Standard_True);
+}
+
+//============================================================================
+const boost::shared_ptr<GeomAPI_Shape>& GeomAlgoAPI_Boolean::shape () const 
+{
+  return myShape;
+}
+
+//============================================================================
+void GeomAlgoAPI_Boolean::mapOfShapes (GeomAPI_DataMapOfShapeShape& theMap) const
+{
+  theMap = myMap;
+}
+
+//============================================================================
+GeomAlgoAPI_MakeShape * GeomAlgoAPI_Boolean::makeShape() const
+{
+  return myMkShape;
+}
+
+//============================================================================
+GeomAlgoAPI_Boolean::~GeomAlgoAPI_Boolean()
+{
+  if (myImpl) {    
+       myMap.clear();
+  }
 }
\ No newline at end of file
index 6a8f9c657f155d3783933181a3aea02dc246f7b5..d095ae13725587132a3d0194b8705e49e4eabee2 100644 (file)
@@ -7,13 +7,15 @@
 
 #include <GeomAlgoAPI.h>
 #include <GeomAPI_Shape.h>
+#include <GeomAlgoAPI_MakeShape.h>
+#include <GeomAPI_DataMapOfShapeShape.h>
 #include <boost/shared_ptr.hpp>
 
 /**\class GeomAlgoAPI_Boolean
  * \ingroup DataAlgo
  * \brief Allows to perform of boolean operations
  */
-class GEOMALGOAPI_EXPORT GeomAlgoAPI_Boolean
+class GeomAlgoAPI_Boolean : public GeomAPI_Interface
 {
  public:
   /* \brief Creates cut boolean operation
@@ -21,24 +23,68 @@ class GEOMALGOAPI_EXPORT GeomAlgoAPI_Boolean
    * \param[in] theTool  toole shape for boolean
    * \return a solid as result of operation
    */
-  static boost::shared_ptr<GeomAPI_Shape> makeCut(boost::shared_ptr<GeomAPI_Shape> theShape,
-                                                        boost::shared_ptr<GeomAPI_Shape> theTool);
+  GEOMALGOAPI_EXPORT static boost::shared_ptr<GeomAPI_Shape> makeCut(
+                                                 boost::shared_ptr<GeomAPI_Shape> theShape,
+                                              boost::shared_ptr<GeomAPI_Shape> theTool);
 
   /* \brief Creates fuse boolean operation
    * \param[in] theShape the main shape
    * \param[in] theTool  second shape
    * \return a solid as result of operation
    */
-  static boost::shared_ptr<GeomAPI_Shape> makeFuse(boost::shared_ptr<GeomAPI_Shape> theShape,
-                                                   boost::shared_ptr<GeomAPI_Shape> theTool);
+  GEOMALGOAPI_EXPORT static boost::shared_ptr<GeomAPI_Shape> makeFuse(
+                                                 boost::shared_ptr<GeomAPI_Shape> theShape,
+                                              boost::shared_ptr<GeomAPI_Shape> theTool);
 
   /* \brief Creates common boolean operation
-   * \param[in] theShape the main shape
+   * \param[in] theObject the main shape
    * \param[in] theTool  second shape
+   * \param[in] theType  type of the operation: Fuse, Cut, Common
    * \return a solid as result of operation
    */
-  static boost::shared_ptr<GeomAPI_Shape> makeCommon(boost::shared_ptr<GeomAPI_Shape> theShape,
-                                                     boost::shared_ptr<GeomAPI_Shape> theTool);
+  GEOMALGOAPI_EXPORT static boost::shared_ptr<GeomAPI_Shape> makeCommon(
+                                                 boost::shared_ptr<GeomAPI_Shape> theObject,
+                                              boost::shared_ptr<GeomAPI_Shape> theTool);
+
+   enum {
+    BOOL_FUSE,
+       BOOL_CUT,
+    BOOL_COMMON
+  };
+  /// Constructor
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Boolean (boost::shared_ptr<GeomAPI_Shape> theObject,
+                                          boost::shared_ptr<GeomAPI_Shape> theTool,
+                                                                                 int theType);
+
+  /// Returns True if algorithm succeed
+  GEOMALGOAPI_EXPORT const bool isDone() const;
+
+  ///  Returns True if resulting shape is valid
+  GEOMALGOAPI_EXPORT const bool isValid() const;
+
+  /// Returns result of the boolean algorithm which may be a Solid or a Face
+  GEOMALGOAPI_EXPORT const boost::shared_ptr<GeomAPI_Shape>& shape () const; 
+  /// Returns map of sub-shapes of the result. To be used for History keeping
+  GEOMALGOAPI_EXPORT void  mapOfShapes (GeomAPI_DataMapOfShapeShape& theMap) const;
+
+  /// Return interface for for History processing
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_MakeShape* makeShape () const;
+
+  ///Destructor
+  GEOMALGOAPI_EXPORT  ~GeomAlgoAPI_Boolean();
+
+  private:
+  /// builds resulting shape
+  void build(boost::shared_ptr<GeomAPI_Shape> theObject,
+             boost::shared_ptr<GeomAPI_Shape> theTool);
+  /// fields
+  double mySize;
+  bool myDone;
+  int  myOperation;
+  boost::shared_ptr<GeomAPI_Shape> myShape;  
+  GeomAPI_DataMapOfShapeShape myMap;
+  GeomAlgoAPI_MakeShape * myMkShape;
 };
 
 #endif
index 6955ee89a96e993929a0865ef9d6147cff0cad5f..d8eefb25d48e1cd0671f9010755540afadede6ca 100644 (file)
@@ -38,7 +38,6 @@ void GeomAlgoAPI_Extrusion::build(const boost::shared_ptr<GeomAPI_Shape>& theBas
 {
   bool isFirstNorm = true;
   gp_Dir aShapeNormal;
-
   TopoDS_Face aBasis = TopoDS::Face(theBasis->impl<TopoDS_Shape>());
   Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(
     BRep_Tool::Surface(aBasis));
@@ -53,29 +52,24 @@ void GeomAlgoAPI_Extrusion::build(const boost::shared_ptr<GeomAPI_Shape>& theBas
   if(aBuilder) {
     setImpl(aBuilder);
     myDone = aBuilder->IsDone() == Standard_True;
-    if (myDone) {
-      BRepCheck_Analyzer aChecker(aBuilder->Shape());
-      myDone = aChecker.IsValid() == Standard_True;
-    }
-    if(myDone) {
+    if (myDone) {       
       TopoDS_Shape aResult;
       if(aBuilder->Shape().ShapeType() == TopAbs_COMPOUND) 
         aResult = GeomAlgoAPI_DFLoader::refineResult(aBuilder->Shape());
       else
         aResult = aBuilder->Shape();
-       
-       for (TopExp_Explorer Exp(aResult,TopAbs_FACE); Exp.More(); Exp.Next()) {
-          boost::shared_ptr<GeomAPI_Shape> aCurrentShape(new GeomAPI_Shape());
-       aCurrentShape->setImpl(new TopoDS_Shape(Exp.Current()));
-          myMap.bind(aCurrentShape, aCurrentShape);
-       }   
+         // fill data map to keep correct orientation of sub-shapes 
+         for (TopExp_Explorer Exp(aResult,TopAbs_FACE); Exp.More(); Exp.Next()) {
+           boost::shared_ptr<GeomAPI_Shape> aCurrentShape(new GeomAPI_Shape());
+        aCurrentShape->setImpl(new TopoDS_Shape(Exp.Current()));
+           myMap.bind(aCurrentShape, aCurrentShape);
+         }   
       myShape->setImpl(new TopoDS_Shape(aResult));
       myFirst->setImpl(new TopoDS_Shape(aBuilder->FirstShape()));
       myLast->setImpl(new TopoDS_Shape(aBuilder-> LastShape()));
          myMkShape = new GeomAlgoAPI_MakeShape (aBuilder);
-    }
-  }    
+       }  
+  }
 }
 
 //============================================================================
@@ -85,7 +79,8 @@ const bool GeomAlgoAPI_Extrusion::isDone() const
 //============================================================================
 const bool GeomAlgoAPI_Extrusion::isValid() const
 {
-  return myDone;
+       BRepCheck_Analyzer aChecker(myShape->impl<TopoDS_Shape>());
+    return (aChecker.IsValid() == Standard_True);
 }
 
 //============================================================================
@@ -104,25 +99,10 @@ const bool GeomAlgoAPI_Extrusion::hasVolume() const
 
 //============================================================================
 const boost::shared_ptr<GeomAPI_Shape>& GeomAlgoAPI_Extrusion::shape () const 
-{return myShape;}
-
-//============================================================================
-/*void GeomAlgoAPI_Extrusion::generated(
-  const boost::shared_ptr<GeomAPI_Shape> theShape, ListOfShape& theHistory)
 {
-  theHistory.clear();
-  if(myDone) {
-    const TopTools_ListOfShape& aList = implPtr<BRepPrimAPI_MakePrism>()
-      ->Generated(theShape->impl<TopoDS_Shape>());
-    TopTools_ListIteratorOfListOfShape it(aList);
-    for(;it.More();it.Next()) {
-      boost::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
-      aShape->setImpl(&(it.Value()));
-      theHistory.push_back(aShape);
-    }
-  }
+  return myShape;
 }
-*/
+
 //============================================================================
 const boost::shared_ptr<GeomAPI_Shape>& GeomAlgoAPI_Extrusion::firstShape()
 {
@@ -152,6 +132,5 @@ GeomAlgoAPI_Extrusion::~GeomAlgoAPI_Extrusion()
 {
   if (myImpl) {    
        myMap.clear();
-       //delete myImpl;
   }
 }
\ No newline at end of file
index 7a033a6aeb61c1095994bfa7553a5f9f88557350..ead8a8a8d446d4e9df18b1b9328f2ea1cdcfaea6 100644 (file)
@@ -8,7 +8,6 @@
 #include <GeomAlgoAPI.h>
 #include <GeomAPI_Shape.h>
 #include <GeomAPI_Dir.h>
-#include <ModelAPI_ResultBody.h>
 #include <GeomAlgoAPI_MakeShape.h>
 #include <GeomAPI_DataMapOfShapeShape.h>
 #include <boost/shared_ptr.hpp>
  * \brief Allows to create the prism based on a given face and a direction
  */
 
-class GeomAlgoAPI_Extrusion : public GeomAPI_Interface//GeomAlgoAPI_MakeShape
+class GeomAlgoAPI_Extrusion : public GeomAPI_Interface
 {
  public:
 
   /* \brief Creates extrusion for the given shape along the normal for this shape
-   * \param[in] theShape face or wire to be extruded
+   * \param[in] theBasis face or wire to be extruded
    * \param[in] theSize  the length of extrusion (if the value is less than 0, the extrusion in opposite normal)
-   * \return a solid or a face which is obtained from specified one
-  
-  static boost::shared_ptr<GeomAPI_Shape> makeExtrusion(boost::shared_ptr<ModelAPI_ResultBody> theResult,
-                                                                                                               boost::shared_ptr<GeomAPI_Shape> theBasis,
-                                                                                                               boost::shared_ptr<GeomAPI_Shape> theContext,
-                                                        double theSize); */
+   * \return a solid or a face/shell which is obtained from specified one  
+   */
   /// Constructor
   GEOMALGOAPI_EXPORT GeomAlgoAPI_Extrusion (boost::shared_ptr<GeomAPI_Shape> theBasis, double theSize);
 
@@ -45,26 +40,24 @@ class GeomAlgoAPI_Extrusion : public GeomAPI_Interface//GeomAlgoAPI_MakeShape
   /// Returns result of the Extrusion algorithm which may be a Solid or a Face
   GEOMALGOAPI_EXPORT const boost::shared_ptr<GeomAPI_Shape>& shape () const;
 
-  /// Returns list of shapes generated from theShape
- // GEOMALGOAPI_EXPORT void generated(const boost::shared_ptr<GeomAPI_Shape> theShape,
-                                   // ListOfShape& theHistory);
-
   /// Returns the first shape 
   GEOMALGOAPI_EXPORT const boost::shared_ptr<GeomAPI_Shape>& firstShape();
 
   /// returns last shape
   GEOMALGOAPI_EXPORT const boost::shared_ptr<GeomAPI_Shape>& lastShape();      
  
-  /// Returns map of sub-shapes of the result
+  /// Returns map of sub-shapes of the result. To be used for History keeping
   GEOMALGOAPI_EXPORT void  mapOfShapes (GeomAPI_DataMapOfShapeShape& theMap) const;
 
+  /// Return interface for for History processing
   GEOMALGOAPI_EXPORT GeomAlgoAPI_MakeShape* makeShape () const;
 
+  /// Destructor
   GEOMALGOAPI_EXPORT  ~GeomAlgoAPI_Extrusion();
 private:
   /// builds resulting shape
   void build(const boost::shared_ptr<GeomAPI_Shape>& theBasis);
-
+  /// fields
   double mySize;
   bool myDone;
   boost::shared_ptr<GeomAPI_Shape> myShape;