// Created on: 1990-12-19
// Created by: Christophe MARION
// Copyright (c) 1990-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.

#ifndef _TopLoc_Location_HeaderFile
#define _TopLoc_Location_HeaderFile

#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>

#include <TopLoc_SListOfItemLocation.hxx>
#include <Standard_Boolean.hxx>
#include <Standard_Integer.hxx>
#include <Standard_OStream.hxx>
class Standard_NoSuchObject;
class Standard_ConstructionError;
class gp_Trsf;
class TopLoc_Datum3D;


//! A Location is a composite transition. It comprises a
//! series of elementary reference coordinates, i.e.
//! objects of type TopLoc_Datum3D, and the powers to
//! which these objects are raised.
class TopLoc_Location 
{
public:

  DEFINE_STANDARD_ALLOC

  
  //! Constructs an empty local coordinate system object.
  //! Note: A Location constructed from a default datum is said to be "empty".
  Standard_EXPORT TopLoc_Location();
  
  //! Constructs the local coordinate system object defined
  //! by the transformation T. T invokes in turn, a TopLoc_Datum3D object.
  Standard_EXPORT TopLoc_Location(const gp_Trsf& T);
  
  //! Constructs the local coordinate system object defined by the 3D datum D.
  //! Exceptions
  //! Standard_ConstructionError if the transformation
  //! T does not represent a 3D coordinate system.
  Standard_EXPORT TopLoc_Location(const Handle(TopLoc_Datum3D)& D);
  
  //! Returns true if this location is equal to the Identity transformation.
    Standard_Boolean IsIdentity() const;
  
  //! Resets this location to the Identity transformation.
    void Identity();
  
  //! Returns    the  first   elementary  datum  of  the
  //! Location.  Use the NextLocation function recursively to access
  //! the other data comprising this location.
  //! Exceptions
  //! Standard_NoSuchObject if this location is empty.
    const Handle(TopLoc_Datum3D)& FirstDatum() const;
  
  //! Returns   the  power  elevation  of    the   first
  //! elementary datum.
  //! Exceptions
  //! Standard_NoSuchObject if this location is empty.
    Standard_Integer FirstPower() const;
  
  //! Returns  a Location representing  <me> without the
  //! first datum. We have the relation :
  //!
  //! <me> = NextLocation() * FirstDatum() ^ FirstPower()
  //! Exceptions
  //! Standard_NoSuchObject if this location is empty.
    const TopLoc_Location& NextLocation() const;
  
  //! Returns  the transformation    associated  to  the
  //! coordinate system.
  Standard_EXPORT const gp_Trsf& Transformation() const;
Standard_EXPORT operator gp_Trsf() const;
  
  //! Returns the inverse of <me>.
  //!
  //! <me> * Inverted() is an Identity.
  Standard_EXPORT Standard_NODISCARD TopLoc_Location Inverted() const;
  
  //! Returns <me> * <Other>, the  elementary datums are
  //! concatenated.
  Standard_EXPORT Standard_NODISCARD TopLoc_Location Multiplied (const TopLoc_Location& Other) const;
Standard_NODISCARD TopLoc_Location operator* (const TopLoc_Location& Other) const
{
  return Multiplied(Other);
}
  
  //! Returns  <me> / <Other>.
  Standard_EXPORT Standard_NODISCARD TopLoc_Location Divided (const TopLoc_Location& Other) const;
Standard_NODISCARD TopLoc_Location operator/ (const TopLoc_Location& Other) const
{
  return Divided(Other);
}
  
  //! Returns <Other>.Inverted() * <me>.
  Standard_EXPORT Standard_NODISCARD TopLoc_Location Predivided (const TopLoc_Location& Other) const;
  
  //! Returns me at the power <pwr>.   If <pwr>  is zero
  //! returns  Identity.  <pwr> can  be lower  than zero
  //! (usual meaning for powers).
  Standard_EXPORT Standard_NODISCARD TopLoc_Location Powered (const Standard_Integer pwr) const;

  //! Returns a hashed value for this local coordinate system. This value is used, with map tables, to store and
  //! retrieve the object easily, and is in the range [1, theUpperBound].
  //! @param theUpperBound the upper bound of the range a computing hash code must be within
  //! @return a computed hash code, in the range [1, theUpperBound]
  Standard_EXPORT Standard_Integer HashCode (Standard_Integer theUpperBound) const;
  
  //! Returns true if this location and the location Other
  //! have the same elementary data, i.e. contain the same
  //! series of TopLoc_Datum3D and respective powers.
  //! This method is an alias for operator ==.
  Standard_EXPORT Standard_Boolean IsEqual (const TopLoc_Location& Other) const;
Standard_Boolean operator == (const TopLoc_Location& Other) const
{
  return IsEqual(Other);
}
  
  //! Returns true if this location and the location Other do
  //! not have the same elementary data, i.e. do not
  //! contain the same series of TopLoc_Datum3D and respective powers.
  //! This method is an alias for operator !=.
  Standard_EXPORT Standard_Boolean IsDifferent (const TopLoc_Location& Other) const;
Standard_Boolean operator != (const TopLoc_Location& Other) const
{
  return IsDifferent(Other);
}
  
  //! Dumps the content of me into the stream
  Standard_EXPORT void DumpJson (Standard_OStream& theOStream, const Standard_Integer theDepth = -1) const;

  //! Prints the contents of <me> on the stream <s>.
  Standard_EXPORT void ShallowDump (Standard_OStream& S) const;




protected:





private:



  TopLoc_SListOfItemLocation myItems;


};


#include <TopLoc_Location.lxx>


//! Computes a hash code for the given location, in the range [1, theUpperBound]
//! @param theLocation the location which hash code is to be computed
//! @param theUpperBound the upper bound of the range a computing hash code must be within
//! @return a computed hash code, in the range [1, theUpperBound]
inline Standard_Integer HashCode (const TopLoc_Location& theLocation, const Standard_Integer theUpperBound)
{
  return theLocation.HashCode (theUpperBound);
}

inline void ShallowDump(const TopLoc_Location& me,Standard_OStream& S) {
 me.ShallowDump(S);
}



#endif // _TopLoc_Location_HeaderFile
