Loading files
f2929057eThis file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 2000-08-22
// Created by: Andrey BETENEV
// Copyright (c) 2000-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.
#include <BRep_Builder.hxx>
#include <BRepTools_Modifier.hxx>
#include <Message_Messenger.hxx>
#include <Message_Msg.hxx>
#include <ShapeBuild_ReShape.hxx>
#include <ShapeExtend_MsgRegistrator.hxx>
#include <ShapeProcess_ShapeContext.hxx>
#include <Standard_Type.hxx>
#include <TCollection_AsciiString.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopoDS_Shape.hxx>
IMPLEMENT_STANDARD_RTTIEXT(ShapeProcess_ShapeContext, ShapeProcess_Context)
//=================================================================================================
ShapeProcess_ShapeContext::ShapeProcess_ShapeContext(const char* const file, const char* const seq)
: ShapeProcess_Context(file, seq),
myUntil(TopAbs_FACE),
myNonManifold(false)
{
}
//=================================================================================================
ShapeProcess_ShapeContext::ShapeProcess_ShapeContext(const TopoDS_Shape& S,
const char* const file,
const char* const seq)
: ShapeProcess_Context(file, seq),
myUntil(TopAbs_FACE),
myNonManifold(false)
{
Init(S);
}
//=================================================================================================
void ShapeProcess_ShapeContext::Init(const TopoDS_Shape& S)
{
myMap.Clear();
myMsg = new ShapeExtend_MsgRegistrator;
myShape = S;
myResult = myShape; //.Nullify();
}
//=================================================================================================
const TopoDS_Shape& ShapeProcess_ShapeContext::Shape() const
{
return myShape;
}
//=================================================================================================
const TopoDS_Shape& ShapeProcess_ShapeContext::Result() const
{
return myResult;
}
//=================================================================================================
const NCollection_DataMap<TopoDS_Shape, TopoDS_Shape, TopTools_ShapeMapHasher>&
ShapeProcess_ShapeContext::Map() const
{
return myMap;
}
//=================================================================================================
occ::handle<ShapeExtend_MsgRegistrator>& ShapeProcess_ShapeContext::Messages()
{
return myMsg;
}
//=================================================================================================
const occ::handle<ShapeExtend_MsgRegistrator>& ShapeProcess_ShapeContext::Messages() const
{
return myMsg;
}
//=================================================================================================
void ShapeProcess_ShapeContext::SetDetalisation(const TopAbs_ShapeEnum level)
{
myUntil = level;
}
//=================================================================================================
TopAbs_ShapeEnum ShapeProcess_ShapeContext::GetDetalisation() const
{
return myUntil;
}
//=================================================================================================
void ShapeProcess_ShapeContext::SetResult(const TopoDS_Shape& res)
{
myResult = res;
myMap.Bind(myShape, myResult);
}
//=================================================================================================
/*
#ifdef OCCT_DEBUG
static void DumpMap (const NCollection_DataMap<TopoDS_Shape, TopoDS_Shape, TopTools_ShapeMapHasher>
&map)
{
std::cout << "----" << std::endl;
std::cout << "Map:" << std::endl;
for (NCollection_DataMap<TopoDS_Shape, TopoDS_Shape, TopTools_ShapeMapHasher>::Iterator It (map);
It.More(); It.Next()) { TopoDS_Shape S0 = It.Key(), S = It.Value(); std::cout <<
S0.TShape()->DynamicType()->Name() << "\t" << *(void**)&S0.TShape() << " \t-> " <<
S.TShape()->DynamicType()->Name() << "\t" << *(void**)&S.TShape() << std::endl;
}
std::cout << "----" << std::endl;
}
#endif
*/
static void RecModif(
const TopoDS_Shape& S,
const NCollection_DataMap<TopoDS_Shape, TopoDS_Shape, TopTools_ShapeMapHasher>& repl,
const occ::handle<ShapeExtend_MsgRegistrator>& msg,
NCollection_DataMap<TopoDS_Shape, TopoDS_Shape, TopTools_ShapeMapHasher>& map,
occ::handle<ShapeExtend_MsgRegistrator>& myMsg,
const TopAbs_ShapeEnum until)
{
TopoDS_Shape r = S;
// gka -modification to keep history for shape with location (OCC21617)
const TopLoc_Location& aShLoc = S.Location();
TopLoc_Location aNullLoc;
r.Location(aNullLoc);
if (map.IsBound(r))
{
r = map.Find(r);
}
if (!r.IsNull())
{
TopoDS_Shape res = r;
if (repl.IsBound(r.Located(aShLoc, false)))
{
res = repl.Find(r.Located(aShLoc, false));
// it is supposed that map is created for r having FORWARD orientation
// hence, if it is reversed, result should be reversed too
// INTERNAL or EXTERNAL orientations are not allowed
if (r.Orientation() != TopAbs_FORWARD)
{
res.Reverse();
}
}
// Treat special case: if S was split, r will be a compound of
// resulting shapes, each to be checked separately
// It is supposed that repl does not contain such splitting
else if (r.ShapeType() < S.ShapeType())
{
TopoDS_Shape result = r.EmptyCopied();
result.Orientation(TopAbs_FORWARD); // protect against INTERNAL or EXTERNAL shapes
bool modif = false;
BRep_Builder B;
for (TopoDS_Iterator it(r, false); it.More(); it.Next())
{
const TopoDS_Shape& sh = it.Value();
if (repl.IsBound(sh))
{
const TopoDS_Shape& newsh = repl.Find(sh);
if (!newsh.IsNull())
{
B.Add(result, newsh);
}
modif = true;
}
else
{
B.Add(result, sh);
}
}
if (modif)
{
if (result.ShapeType() == TopAbs_WIRE || result.ShapeType() == TopAbs_SHELL)
{
result.Closed(BRep_Tool::IsClosed(result));
}
res = result;
}
}
if (res != r)
{
map.Bind(S.Located(aNullLoc), res);
}
}
// update messages (messages must be taken from each level in the substitution map)
if (!r.IsNull() && !myMsg.IsNull() && !msg.IsNull() && msg->MapShape().Extent() > 0)
{
const NCollection_DataMap<TopoDS_Shape, NCollection_List<Message_Msg>, TopTools_ShapeMapHasher>&
msgmap = msg->MapShape();
if (msgmap.IsBound(r))
{
const NCollection_List<Message_Msg>& msglist = msgmap.Find(r);
for (NCollection_List<Message_Msg>::Iterator iter(msglist); iter.More(); iter.Next())
{
myMsg->Send(S, iter.Value(), Message_Warning);
}
}
else if (msgmap.IsBound(S))
{
const NCollection_List<Message_Msg>& msglist = msgmap.Find(S);
for (NCollection_List<Message_Msg>::Iterator iter(msglist); iter.More(); iter.Next())
{
myMsg->Send(S, iter.Value(), Message_Warning);
}
}
}
if (until == TopAbs_SHAPE || S.ShapeType() >= until)
{
return;
}
for (TopoDS_Iterator it(S); it.More(); it.Next())
{
RecModif(it.Value(), repl, msg, map, myMsg, until);
}
}
void ShapeProcess_ShapeContext::RecordModification(
const NCollection_DataMap<TopoDS_Shape, TopoDS_Shape, TopTools_ShapeMapHasher>& repl,
const occ::handle<ShapeExtend_MsgRegistrator>& msg)
{
if (repl.Extent() <= 0)
{
return;
}
RecModif(myShape, repl, msg, myMap, myMsg, myUntil);
if (myMap.IsBound(myShape))
{
myResult = myMap.Find(myShape);
}
#ifdef OCCT_DEBUG
// std::cout << "Modifier: " << std::endl; DumpMap (myMap);
#endif
}
//=================================================================================================
static void RecModif(const TopoDS_Shape& S,
const occ::handle<ShapeBuild_ReShape>& repl,
const occ::handle<ShapeExtend_MsgRegistrator>& msg,
NCollection_DataMap<TopoDS_Shape, TopoDS_Shape, TopTools_ShapeMapHasher>& map,
occ::handle<ShapeExtend_MsgRegistrator>& myMsg,
const TopAbs_ShapeEnum until)
{
if (S.IsNull())
{
return;
}
// gka -modification to keep history for shape with location (OCC21617)
TopLoc_Location aNullLoc;
TopoDS_Shape aS = S.Located(aNullLoc);
TopoDS_Shape r = aS;
if (map.IsBound(r))
{
r = map.Find(r);
}
if (!r.IsNull())
{
TopoDS_Shape res;
if (repl->Status(r, res, true) && res != r)
{
map.Bind(aS, res);
// Treat special case: if S was split, r will be a compound of
// resulting shapes, recursive procedure should be applied
}
else if (r.ShapeType() < S.ShapeType())
{
res = repl->Apply(r, (TopAbs_ShapeEnum)((int)S.ShapeType() + 1));
if (res != r)
{
map.Bind(aS, res);
}
}
}
// update messages (messages must be taken from each level in the substitution map)
if (!r.IsNull() && !myMsg.IsNull() && !msg.IsNull() && msg->MapShape().Extent() > 0)
{
TopoDS_Shape cur, next = r;
const NCollection_DataMap<TopoDS_Shape, NCollection_List<Message_Msg>, TopTools_ShapeMapHasher>&
msgmap = msg->MapShape();
if (msgmap.IsBound(S))
{
next = S;
}
do
{
cur = next;
if (msgmap.IsBound(cur))
{
const NCollection_List<Message_Msg>& msglist = msgmap.Find(cur);
for (NCollection_List<Message_Msg>::Iterator iter(msglist); iter.More(); iter.Next())
{
myMsg->Send(S, iter.Value(), Message_Warning);
}
}
next = repl->Value(cur);
} while (!next.IsNull() && cur != next);
}
if (until == TopAbs_SHAPE || S.ShapeType() >= until)
{
return;
}
for (TopoDS_Iterator it(S, false /*,false*/); it.More(); it.Next())
{
RecModif(it.Value(), repl, msg, map, myMsg, until);
}
}
void ShapeProcess_ShapeContext::RecordModification(
const occ::handle<ShapeBuild_ReShape>& repl,
const occ::handle<ShapeExtend_MsgRegistrator>& msg)
{
RecModif(myShape, repl, msg, myMap, myMsg, myUntil);
if (myMap.IsBound(myShape))
{
myResult = myMap.Find(myShape);
myResult.Location(myShape.Location(), false);
}
#ifdef OCCT_DEBUG
// std::cout << "ReShape: " << std::endl; DumpMap (myMap);
#endif
}
//=================================================================================================
void ShapeProcess_ShapeContext::RecordModification(const occ::handle<ShapeBuild_ReShape>& repl)
{
occ::handle<ShapeExtend_MsgRegistrator> msg;
RecordModification(repl, msg);
}
//=================================================================================================
void ShapeProcess_ShapeContext::AddMessage(const TopoDS_Shape& S,
const Message_Msg& msg,
const Message_Gravity grv)
{
if (!myMsg.IsNull())
{
myMsg->Send(S, msg, grv);
}
}
//=================================================================================================
static void ExplodeModifier(
const TopoDS_Shape& S,
const BRepTools_Modifier& repl,
NCollection_DataMap<TopoDS_Shape, TopoDS_Shape, TopTools_ShapeMapHasher>& map,
const TopAbs_ShapeEnum until)
{
const TopoDS_Shape& res = repl.ModifiedShape(S);
if (res != S)
{
map.Bind(S, res);
}
if (until == TopAbs_SHAPE || S.ShapeType() >= until)
{
return;
}
for (TopoDS_Iterator it(S); it.More(); it.Next())
{
ExplodeModifier(it.Value(), repl, map, until);
}
}
void ShapeProcess_ShapeContext::RecordModification(
const TopoDS_Shape& S,
const BRepTools_Modifier& repl,
const occ::handle<ShapeExtend_MsgRegistrator>& msg)
{
NCollection_DataMap<TopoDS_Shape, TopoDS_Shape, TopTools_ShapeMapHasher> map;
ExplodeModifier(S, repl, map, myUntil);
RecordModification(map, msg);
}
//=================================================================================================
bool ShapeProcess_ShapeContext::GetContinuity(const char* const param, GeomAbs_Shape& cont) const
{
TCollection_AsciiString str;
if (!GetString(param, str))
{
return false;
}
str.LeftAdjust();
str.RightAdjust();
str.UpperCase();
if (str.IsEqual("C0"))
{
cont = GeomAbs_C0;
}
else if (str.IsEqual("G1"))
{
cont = GeomAbs_G1;
}
else if (str.IsEqual("C1"))
{
cont = GeomAbs_C1;
}
else if (str.IsEqual("G2"))
{
cont = GeomAbs_G2;
}
else if (str.IsEqual("C2"))
{
cont = GeomAbs_C2;
}
else if (str.IsEqual("C3"))
{
cont = GeomAbs_C3;
}
else if (str.IsEqual("CN"))
{
cont = GeomAbs_CN;
}
else
{
return false;
}
return true;
}
//=================================================================================================
GeomAbs_Shape ShapeProcess_ShapeContext::ContinuityVal(const char* const param,
const GeomAbs_Shape def) const
{
GeomAbs_Shape val;
return GetContinuity(param, val) ? val : def;
}
//=================================================================================================
void ShapeProcess_ShapeContext::PrintStatistics() const
{
int SS = 0, SN = 0, FF = 0, FS = 0, FN = 0;
for (NCollection_DataMap<TopoDS_Shape, TopoDS_Shape, TopTools_ShapeMapHasher>::Iterator It(myMap);
It.More();
It.Next())
{
TopoDS_Shape keyshape = It.Key(), valueshape = It.Value();
if (keyshape.ShapeType() == TopAbs_SHELL)
{
if (valueshape.IsNull())
{
SN++;
}
else
{
SS++;
}
}
else if (keyshape.ShapeType() == TopAbs_FACE)
{
if (valueshape.IsNull())
{
FN++;
}
else if (valueshape.ShapeType() == TopAbs_SHELL)
{
FS++;
}
else
{
FF++;
}
}
}
// mapping
Message_Msg EPMSG100("PrResult.Print.MSG100"); // Mapping:
Messenger()->Send(EPMSG100, Message_Info);
Message_Msg TPMSG50("PrResult.Print.MSG50"); // Shells:
Messenger()->Send(TPMSG50, Message_Info);
Message_Msg EPMSG110("PrResult.Print.MSG110"); // Result is Shell : %d
EPMSG110.Arg(SS);
Messenger()->Send(EPMSG110, Message_Info);
Message_Msg EPMSG150("PrResult.Print.MSG150"); // No Result : %d
EPMSG150.Arg(SN);
Messenger()->Send(EPMSG150.Get(), Message_Info);
TCollection_AsciiString tmp110(EPMSG110.Original()), tmp150(EPMSG150.Original());
EPMSG110.Set(tmp110.ToCString());
EPMSG150.Set(tmp150.ToCString());
Message_Msg TPMSG55("PrResult.Print.MSG55"); // Faces:
Messenger()->Send(TPMSG55, Message_Info);
Message_Msg EPMSG115("PrResult.Print.MSG115"); // Result is Face : %d
EPMSG115.Arg(FF);
Messenger()->Send(EPMSG115, Message_Info);
EPMSG110.Arg(FS);
Messenger()->Send(EPMSG110, Message_Info);
EPMSG150.Arg(FN);
Messenger()->Send(EPMSG150, Message_Info);
// preparation ratio
double SPR = 1, FPR = 1;
int STotalR = SS, FTotalR = FF + FS;
int NbS = STotalR + SN, NbF = FTotalR + FN;
if (NbS > 0)
{
SPR = 1. * (NbS - SN) / NbS;
}
if (NbF > 0)
{
FPR = 1. * (NbF - FN) / NbF;
}
Message_Msg PMSG200("PrResult.Print.MSG200"); // Preparation ratio:
Messenger()->Send(PMSG200, Message_Info);
Message_Msg PMSG205("PrResult.Print.MSG205"); // Shells: %d per cent
PMSG205.Arg((int)(100. * SPR));
Messenger()->Send(PMSG205, Message_Info);
Message_Msg PMSG210("PrResult.Print.MSG210"); // Faces : %d per cent
PMSG210.Arg((int)(100. * FPR));
Messenger()->Send(PMSG210, Message_Info);
}