// Created on: 1991-01-21 // Created by: Christophe MARION // Copyright (c) 1991-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 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. #define No_Standard_NoSuchObject #include #include #include #include #include #include #include static const gp_Trsf TheIdentity; static Standard_Boolean IsInternalIdentity(const TopLoc_Location& loc) { if (loc.IsIdentity()) { return Standard_True; } // if (loc.FirstDatum()->Transformation().Form() == gp_Identity) { // return Standard_True; // } return Standard_False; } //======================================================================= //function : TopLoc_Location //purpose : constructor Identity //======================================================================= TopLoc_Location::TopLoc_Location () { } //======================================================================= //function : TopLoc_Location //purpose : constructor Datum //======================================================================= TopLoc_Location::TopLoc_Location (const Handle(TopLoc_Datum3D)& D) { myItems.Construct(TopLoc_ItemLocation(D,1)); } //======================================================================= //function : TopLoc_Location //purpose : //======================================================================= TopLoc_Location::TopLoc_Location(const gp_Trsf& T) { Handle(TopLoc_Datum3D) D = new TopLoc_Datum3D(T); myItems.Construct(TopLoc_ItemLocation(D,1)); } //======================================================================= //function : Transformation //purpose : //======================================================================= const gp_Trsf& TopLoc_Location::Transformation() const { if (IsInternalIdentity(*this)) return TheIdentity; else { if (myItems.Value().myTrsf == NULL) { TopLoc_ItemLocation *I = (TopLoc_ItemLocation*) (void*) &this->myItems.Value(); // CLE if (I->myTrsf == NULL) I->myTrsf = new gp_Trsf; *(I->myTrsf) = I->myDatum->Transformation(); I->myTrsf->Power(I->myPower); I->myTrsf->PreMultiply(NextLocation().Transformation()); } return *(myItems.Value().myTrsf); } } TopLoc_Location::operator gp_Trsf() const { return Transformation(); } //======================================================================= //function : Inverted //purpose : return the inverse //======================================================================= TopLoc_Location TopLoc_Location::Inverted () const { // // the inverse of a Location is a chain in revert order // with opposite powers and same Local // TopLoc_Location result; TopLoc_SListOfItemLocation items = myItems; while (items.More()) { result.myItems.Construct(TopLoc_ItemLocation(items.Value().myDatum, -items.Value().myPower)); items.Next(); } return result; } //======================================================================= //function : Multiplied //purpose : operator * //======================================================================= TopLoc_Location TopLoc_Location::Multiplied(const TopLoc_Location& Other) const { // prepend the chain Other in front of this // cancelling null exponents if (IsIdentity()) return Other; if (Other.IsIdentity()) return *this; // prepend the queue of Other TopLoc_Location result = Multiplied(Other.NextLocation()); // does the head of Other cancel the head of result Standard_Integer p = Other.FirstPower(); if (!result.IsIdentity()) { if (Other.FirstDatum() == result.FirstDatum()) { p += result.FirstPower(); result.myItems.ToTail(); } } if (p != 0) result.myItems.Construct(TopLoc_ItemLocation(Other.FirstDatum(),p)); return result; } //======================================================================= //function : Divided //purpose : operator / this*Other.Inverted() //======================================================================= TopLoc_Location TopLoc_Location::Divided (const TopLoc_Location& Other) const { return Multiplied(Other.Inverted()); } //======================================================================= //function : Predivided //purpose : return Other.Inverted() * this //======================================================================= TopLoc_Location TopLoc_Location::Predivided (const TopLoc_Location& Other) const { return Other.Inverted().Multiplied(*this); } //======================================================================= //function : Powered //purpose : power elevation //======================================================================= TopLoc_Location TopLoc_Location::Powered (const Standard_Integer pwr) const { if (IsInternalIdentity(*this)) return *this; if (pwr == 1) return *this; if (pwr == 0) return TopLoc_Location(); // optimisation when just one element if (myItems.Tail().IsEmpty()) { TopLoc_Location result; result.myItems.Construct(TopLoc_ItemLocation(FirstDatum(), FirstPower() * pwr)); return result; } if (pwr > 0) return Multiplied(Powered(pwr - 1)); else return Inverted().Powered(-pwr); } //======================================================================= //function : HashCode //purpose : //======================================================================= Standard_Integer TopLoc_Location::HashCode(const Standard_Integer upper) const { // the HashCode computed for a Location is the bitwise exclusive or // of values computed for each element of the list // to compute this value, the depth of the element is computed // the depth is the position of the element in the list // this depth is multiplied by 3 // each element is an elementary Datum raised to a Power // the Power is bitwise left shifted by depth // this is added to the HashCode of the Datum // this value is biwise rotated by depth // the use of depth avoids getting the same result for two permutated lists. Standard_Integer depth = 0; unsigned int h = 0; TopLoc_SListOfItemLocation items = myItems; while (items.More()) { depth += 3; unsigned int i = ::HashCode (items.Value().myDatum, upper); unsigned int j = ( (i + items.Value().myPower) <>(32-depth) | j<ShallowDump(S); items.Next(); } S << "\n"; }