1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-16 10:08:36 +03:00
occt/src/IGESData/IGESData_ToolLocation.cxx

256 lines
9.5 KiB
C++

// 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.
//szv#9:PRO19565:04Oct99 loss of rotation matrix corrected
#include <gp_Ax3.hxx>
#include <gp_Dir.hxx>
#include <gp_GTrsf.hxx>
#include <gp_Pnt.hxx>
#include <gp_Trsf.hxx>
#include <gp_XYZ.hxx>
#include <IGESData_GeneralModule.hxx>
#include <IGESData_IGESModel.hxx>
#include <IGESData_Protocol.hxx>
#include <IGESData_SingleParentEntity.hxx>
#include <IGESData_ToolLocation.hxx>
#include <IGESData_TransfEntity.hxx>
#include <Interface_EntityIterator.hxx>
#include <Interface_Macros.hxx>
#include <Standard_DomainError.hxx>
#include <Standard_Type.hxx>
IMPLEMENT_STANDARD_RTTIEXT(IGESData_ToolLocation,Standard_Transient)
#define TYPEFORASSOC 402
IGESData_ToolLocation::IGESData_ToolLocation (const Handle(IGESData_IGESModel)& amodel,
const Handle(IGESData_Protocol)& protocol)
: thelib (protocol),
therefs (0,amodel->NbEntities()),
theassocs (0,amodel->NbEntities())
{
theprec = 1.e-05;
themodel = amodel;
therefs.Init(0); theassocs.Init(0);
Load();
}
void IGESData_ToolLocation::Load ()
{
// Pour chaque Entite, sauf Transf et Assoc (sauf SingleParent), on considere
// ses "OwnShared" comme etant dependents
Standard_Integer nb = themodel->NbEntities();
for (Standard_Integer i = 1; i <= nb; i ++) {
Handle(IGESData_IGESEntity) ent = themodel->Entity(i);
if (ent->IsKind(STANDARD_TYPE(IGESData_TransfEntity))) continue;
// Cas de SingleParentEntity
if (ent->IsKind(STANDARD_TYPE(IGESData_SingleParentEntity))) {
DeclareAndCast(IGESData_SingleParentEntity,assoc,ent);
Standard_Integer nbc = assoc->NbChildren();
Handle(IGESData_IGESEntity) parent = assoc->SingleParent();
for (Standard_Integer j = 1; j <= nbc; j ++)
SetParentAssoc(parent,assoc->Child(j));
continue;
}
if (ent->TypeNumber() == TYPEFORASSOC) continue; // Assoc sauf SingleParent
// Cas courant
SetOwnAsDependent (ent); // qui opere
}
}
void IGESData_ToolLocation::SetPrecision (const Standard_Real prec)
{ theprec = prec; }
void IGESData_ToolLocation::SetReference (const Handle(IGESData_IGESEntity)& parent,
const Handle(IGESData_IGESEntity)& child)
{
Standard_Integer np = themodel->Number(parent);
Standard_Integer nc = themodel->Number(child);
if (np == 0 || nc == 0) return;
if (therefs(nc) > 0) np = -1; // note ambigu
therefs.SetValue(nc,np);
}
void IGESData_ToolLocation::SetParentAssoc (const Handle(IGESData_IGESEntity)& parent,
const Handle(IGESData_IGESEntity)& child)
{
Standard_Integer np = themodel->Number(parent);
Standard_Integer nc = themodel->Number(child);
if (np == 0 || nc == 0) return;
if (theassocs(nc) > 0) np = -1; // note ambigu
theassocs.SetValue(nc,np);
}
void IGESData_ToolLocation::ResetDependences (const Handle(IGESData_IGESEntity)& child)
{
Standard_Integer nc = themodel->Number(child);
if (nc == 0) return;
therefs.SetValue(nc,0);
theassocs.SetValue(nc,0);
}
void IGESData_ToolLocation::SetOwnAsDependent (const Handle(IGESData_IGESEntity)& ent)
{
Standard_Integer CN;
Handle(Interface_GeneralModule) gmodule;
if (!thelib.Select(ent,gmodule,CN)) return;
Handle(IGESData_GeneralModule) module =
Handle(IGESData_GeneralModule)::DownCast (gmodule);
Interface_EntityIterator list;
module->OwnSharedCase(CN,ent,list);
// Remarque : en toute rigueur, il faudrait ignorer les entites referencees
// dont le SubordinateStatus vaut 0 ou 2 ...
// Question : ce Status est-il toujours bien comme il faut ?
for (list.Start(); list.More(); list.Next())
SetReference (ent, GetCasted(IGESData_IGESEntity,list.Value()) );
}
// #########################################################################
// ######## RESULTATS ########
Standard_Boolean IGESData_ToolLocation::IsTransf
(const Handle(IGESData_IGESEntity)& ent) const
{ return ent->IsKind(STANDARD_TYPE(IGESData_TransfEntity)); }
Standard_Boolean IGESData_ToolLocation::IsAssociativity
(const Handle(IGESData_IGESEntity)& ent) const
{ return (ent->TypeNumber() == TYPEFORASSOC); }
Standard_Boolean IGESData_ToolLocation::HasTransf
(const Handle(IGESData_IGESEntity)& ent) const
{ return ent->HasTransf(); }
gp_GTrsf IGESData_ToolLocation::ExplicitLocation
(const Handle(IGESData_IGESEntity)& ent) const
{ return ent->Location(); }
Standard_Boolean IGESData_ToolLocation::IsAmbiguous
(const Handle(IGESData_IGESEntity)& ent) const
{
Standard_Integer num = themodel->Number(ent);
if (num == 0) return Standard_False;
if (therefs(num) < 0 || theassocs(num) < 0) return Standard_True;
if (therefs(num) != 0 && theassocs(num) != 0) return Standard_True;
return Standard_False;
}
Standard_Boolean IGESData_ToolLocation::HasParent
(const Handle(IGESData_IGESEntity)& ent) const
{
Standard_Integer num = themodel->Number(ent);
if (num == 0) return Standard_False;
if (therefs(num) < 0 || theassocs(num) < 0) throw Standard_DomainError("IGESData_ToolLocation : HasParent");
if (therefs(num) != 0 && theassocs(num) != 0) throw Standard_DomainError("IGESData_ToolLocation : HasParent");
if (therefs(num) != 0 || theassocs(num) != 0) return Standard_True;
return Standard_False;
}
Handle(IGESData_IGESEntity) IGESData_ToolLocation::Parent
(const Handle(IGESData_IGESEntity)& ent) const
{
Handle(IGESData_IGESEntity) parent;
Standard_Integer num = themodel->Number(ent);
if (num == 0) return parent;
if (therefs(num) < 0 || theassocs(num) < 0) throw Standard_DomainError("IGESData_ToolLocation : Parent");
if (therefs(num) != 0 && theassocs(num) != 0) throw Standard_DomainError("IGESData_ToolLocation : Parent");
if (therefs(num) != 0) parent = themodel->Entity (therefs (num));
if (theassocs(num) != 0) parent = themodel->Entity (theassocs (num));
return parent;
}
Standard_Boolean IGESData_ToolLocation::HasParentByAssociativity
(const Handle(IGESData_IGESEntity)& ent) const
{
Standard_Integer num = themodel->Number(ent);
if (num == 0) return Standard_False;
if (therefs(num) < 0 || theassocs(num) < 0) throw Standard_DomainError("IGESData_ToolLocation : HasParentByAssociativity");
if (therefs(num) != 0 && theassocs(num) != 0) throw Standard_DomainError("IGESData_ToolLocation : HasParentByAssociativity");
if (theassocs(num) != 0) return Standard_True;
return Standard_False;
}
gp_GTrsf IGESData_ToolLocation::ParentLocation
(const Handle(IGESData_IGESEntity)& ent) const
{
gp_GTrsf locat; // par defaut, identite
Handle(IGESData_IGESEntity) parent = Parent(ent);
// Definition recursive
if (!parent.IsNull()) locat = EffectiveLocation(parent);
return locat;
}
gp_GTrsf IGESData_ToolLocation::EffectiveLocation
(const Handle(IGESData_IGESEntity)& ent) const
{
gp_GTrsf locat = ent->Location();
// Combiner Transf et ParentLocation
locat.PreMultiply (ParentLocation(ent)); // ne pas se tromper de sens !
return locat;
}
Standard_Boolean IGESData_ToolLocation::AnalyseLocation (const gp_GTrsf& loc,
gp_Trsf& result) const
{ return ConvertLocation (theprec,loc,result); }
Standard_Boolean IGESData_ToolLocation::ConvertLocation (const Standard_Real prec,
const gp_GTrsf& loc,
gp_Trsf& result,
const Standard_Real unit)
{
if (result.Form() != gp_Identity) result = gp_Trsf(); // Identite forcee au depart
// On prend le contenu de <loc>. Attention a l adressage
gp_XYZ v1 ( loc.Value(1,1), loc.Value(1,2), loc.Value(1,3) );
gp_XYZ v2 ( loc.Value(2,1), loc.Value(2,2), loc.Value(2,3) );
gp_XYZ v3 ( loc.Value(3,1), loc.Value(3,2), loc.Value(3,3) );
// A-t-on affaire a une similitude ?
Standard_Real m1 = v1.Modulus();
Standard_Real m2 = v2.Modulus();
Standard_Real m3 = v3.Modulus();
// D abord est-elle singuliere cette matrice ?
if (m1 < prec || m2 < prec || m3 < prec) return Standard_False;
Standard_Real mm = (m1+m2+m3)/3.; // voici la Norme moyenne, cf Scale
if ( Abs(m1 - mm) > prec*mm ||
Abs(m2 - mm) > prec*mm ||
Abs(m3 - mm) > prec*mm ) return Standard_False;
v1.Divide(m1);
v2.Divide(m2);
v3.Divide(m3);
if ( Abs(v1.Dot(v2)) > prec ||
Abs(v2.Dot(v3)) > prec ||
Abs(v3.Dot(v1)) > prec ) return Standard_False;
// Ici, Orthogonale et memes normes. En plus on l a Normee
// Restent les autres caracteristiques :
if (Abs(mm - 1.) > prec) result.SetScale(gp_Pnt(0,0,0),mm);
gp_XYZ tp = loc.TranslationPart();
if (unit != 1.) tp.Multiply(unit);
if (tp.X() != 0. || tp.Y() != 0. || tp.Z() != 0.) result.SetTranslationPart(tp);
// On isole le cas de l Identite (tellement facile et avantageux)
if (v1.X() != 1. || v1.Y() != 0. || v1.Z() != 0. ||
v2.X() != 0. || v2.Y() != 1. || v2.Z() != 0. ||
v3.X() != 0. || v3.Y() != 0. || v3.Z() != 1. ) {
// Pas Identite : vraie construction depuis un Ax3
gp_Dir d1(v1);
gp_Dir d2(v2);
gp_Dir d3(v3);
gp_Ax3 axes (gp_Pnt(0,0,0),d3,d1);
d3.Cross(d1);
if (d3.Dot(d2) < 0) axes.YReverse();
gp_Trsf transf;
transf.SetTransformation(axes);
result *= transf; //szv#9:PRO19565:04Oct99
}
return Standard_True;
}