HLRBRep problem in 6.3

Hello everyone.

I'm trying to compute the silhouette of an object. I want *only* the outline. However, OutlineVCompound only contains part of the outline. I have to use VCompound for the rest, and that contains edges which aren't part of the outline. From the docs, it sounds like OutlineVCompound should contain everything I need, but it doesn't. So, how do I figure out which of the edges in OutlineVCompound and VCompound are the outline, and which ones aren't?

The shapes I've tried are a cylinder, and a cylinder with a half-sphere on one end (i.e. a ballnose endmill). For the cylinder, OutlineVCompound contains a single edge when displayed. For the ballnose, it contains a 'J' shape - the outline of the half-sphere and of one side of the cylinder.

Here's the code I'm using:
TopoDS_Shape t = ...
gp_Trsf pTrsf = ...
Handle(HLRBRep_Algo) myAlgo = new HLRBRep_Algo();
myAlgo->Add(t);
myAlgo->Projector(HLRAlgo_Projector (pTrsf,false,0)); //instead of Prs3d_Projector
myAlgo->Update();
myAlgo->Hide(); //from modalg.pdf
HLRBRep_HLRToShape aHLRToShape(myAlgo);
TopoDS_Shape o = aHLRToShape.OutlineVCompound();
TopoDS_Shape v = aHLRToShape.VCompound();

JuryS's picture

Here is my code. Your problem that you don't use Rg1LineVCompound and OutLineVCompound.

bool DocumentCommon::onHideLines()
{
CleanAfterTexture();
CleanAfterHideLine();
ShowHatches();

TopoDS_Shape Shape;
Handle_HLRBRep_Algo myAlgo = new HLRBRep_Algo();
HLRBRep_HLRToShape aHLRToShape(myAlgo);
bool hasOne = false;
Handle_TPrsStd_AISPresentation CurrentPrs;
Handle_TNaming_NamedShape myShape;
TDF_Label LabObject;
AIS_ListOfInteractive aList;
AIS_ListIteratorOfListOfInteractive aListIterator;

Standard_Real DX,DY,DZ,XAt,YAt,ZAt,Vx,Vy,Vz;
Standard_Boolean IsPerspective;
gp_Pnt rightBottom, leftBottom, leftTop, rightTop;
Quantity_Length aFocus = 1;
uint myX,myY;

QWorkspace* ws = myApp->getWorkspace();
MDIWindow* w = (MDIWindow*) ws->activeWindow();
View* myView = w->getView();

myX = ws->activeWindow()->size().width();
myY = ws->activeWindow()->size().height();

myView->GetProjData(DX,DY,DZ,XAt,YAt,ZAt,Vx,Vy,Vz,IsPerspective,rightBottom, leftBottom, leftTop, rightTop, myX, myY);

Prs3d_Projector aPrs3d_Projector(IsPerspective,aFocus,DX,DY,DZ,XAt,YAt,ZAt,Vx,Vy,Vz);
HLRAlgo_Projector myProjector = aPrs3d_Projector.Projector();
myAlgo->Projector(myProjector);

//! Ñòðîþ 2 ëèíèè, ÷òîáû îïèñàòü â ðàìêó òåêóùèé âèä
TopoDS_Shape L1 = BRepBuilderAPI_MakeEdge(rightBottom,leftBottom);
TopoDS_Shape L2 = BRepBuilderAPI_MakeEdge(rightBottom,rightTop);
myAlgo->Add(L1,0); myAlgo->Add(L2,0);

//! Âûòàñêèâàþ èõ èç àëãîðèòìà
myAlgo->Update();
TopoDS_Shape myPointsShape = aHLRToShape.VCompound();
myAlgo->Remove(1);
myAlgo->Remove(2);

bool First(true);
gp_Pnt pt;
double Xmin(0),Ymin(0),Xmax(0),Ymax(0);
TopoDS_Vertex vertex;

for (TopExp_Explorer myExplorer(myPointsShape, TopAbs_COMPOUND); myExplorer.More(); myExplorer.Next())
{
for (TopExp_Explorer myPointExplorer(myExplorer.Current(),TopAbs_VERTEX); myPointExplorer.More(); myPointExplorer.Next())
{
vertex = TopoDS::Vertex(myPointExplorer.Current());
pt = BRep_Tool::Pnt(vertex);
if (First)
{
Xmin = pt.X(); Xmax = pt.X();
Ymin = pt.Y(); Ymax = pt.Y();
}
else
{
if (pt.X()Xmax) Xmax = pt.X();
if (pt.Y()Ymax) Ymax = pt.Y();
}
First = false;
}
}
gp_Pnt myControlPoint1(Xmin,Ymax,0);
gp_Pnt myControlPoint2(Xmax,Ymax,0);
gp_Pnt myControlPoint3(Xmax,Ymin,0);
gp_Pnt myControlPoint4(Xmin,Ymin,0);

myContext->DisplayedObjects(aList);
for(aListIterator.Initialize(aList);aListIterator.More();aListIterator.Next())
{
CurrentPrs = Handle(TPrsStd_AISPresentation)::DownCast(aListIterator.Value()->GetOwner());
if (CurrentPrs.IsNull()) continue; //Åñëè îáúåêò áåç àòòðèáóòîâ ïðåðûâàþñü
LabObject = CurrentPrs->Label();
if (!LabObject.FindAttribute(TNaming_NamedShape::GetID(),myShape)) continue; //Åñëè íå íàéäåíî òåëî ïðåðûâàþñü
myAlgo->Add(myShape->Get(),0);
hasOne = true;
myContext->SetDisplayMode(CurrentPrs->GetAIS(), 3, Standard_False); //Ïðÿ÷ó îáúåêò
}
if (!hasOne) return true; //Åñëè íè îäíîãî îáúåêòà íå îòðàáîòàíî

myAlgo->Update();
myAlgo->Hide();

//TopoDS_Shape needRotateShape = aHLRToShape.VCompound();

TopoDS_Compound comp;
BRep_Builder builder;
builder.MakeCompound( comp );

TopoDS_Shape VCompound = aHLRToShape.VCompound(); //Ëèíèè òåë
TopoDS_Shape Rg1LineVCompound = aHLRToShape.Rg1LineVCompound(); //Äóáëèðóþùèå ëèíèè â ìåñòàõ ïåðåõîäîâ
//TopoDS_Shape RgNLineVCompound = aHLRToShape.RgNLineVCompound(); //Ðàçäåëèòåëüíûå ëèíèè (íà öèëèíäðå îäíà âäîëü)
TopoDS_Shape OutLineVCompound = aHLRToShape.OutLineVCompound(); //Íàðóæíûå ëèíèè
// TopoDS_Shape IsoLineVCompound = aHLRToShape.IsoLineVCompound(); //Ëèíèè àéñî, ìîæíî óêàçàòü ïðè âêëþ÷åíèè òåëà â àëãîðèòì

if (!VCompound.IsNull())
builder.Add(comp, VCompound);

if (!Rg1LineVCompound.IsNull())
builder.Add(comp, Rg1LineVCompound);

//if (!RgNLineVCompound.IsNull())
// builder.Add(comp, RgNLineVCompound);

if (!OutLineVCompound.IsNull())
builder.Add(comp, OutLineVCompound);

// if (!IsoLineVCompound.IsNull())
// builder.Add(comp, IsoLineVCompound);

gp_Trsf trsf;
gp_Vec myVec1(myControlPoint3,myControlPoint4);
gp_Vec myVec2(myControlPoint3,myControlPoint2);
gp_Dir myDir1(myVec1);
gp_Dir myDir2(myVec2);
gp_Ax2 ax2forshape(myControlPoint3,myDir1,myDir2);
gp_Ax3 ax3forshape(ax2forshape);

gp_Vec myVec3(rightBottom,leftBottom);
gp_Vec myVec4(rightBottom,rightTop);
gp_Dir myDir3(myVec3);
gp_Dir myDir4(myVec4);
gp_Ax2 ax2forview(rightBottom,myDir3,myDir4);
gp_Ax3 ax3forview(ax2forview);

trsf.SetDisplacement(ax3forshape,ax3forview);
BRepBuilderAPI_Transform MoveByControlPoint(comp,trsf,Standard_False);

myShapeForHideLine = new AIS_Shape(MoveByControlPoint);
myShapeForHideLine->SetInfiniteState(Standard_True);
myContext->SetColor(myShapeForHideLine,Quantity_NOC_BLACK,Standard_False);
myContext->Display(myShapeForHideLine,0,-1,Standard_False,Standard_False);

hasHideLines = true;
myContext->UpdateCurrentViewer();
return true;
}

Mark's picture

Hi JuryS.

I am using OutLineVCompound; I typed that part by hand, and used a lowercase l accidentally. The actual code wouldn't have compiled with a typo like that.

Rg1LineVCompound doesn't have anything in it when I try to display it.

I'll copy and paste your code, and see if I get a different result.

Something else I noticed is that the position of the projection seems to depend on the size of the object. I made the object 10x larger, and the projection shifted. I can't find a way to specify where the projection should end up at.

Thanks
Mark

JuryS's picture

myView->GetProjData(DX,DY,DZ,XAt,YAt,ZAt,Vx,Vy,Vz,IsPerspective,rightBottom, leftBottom, leftTop, rightTop, myX, myY);

Prs3d_Projector aPrs3d_Projector(IsPerspective,aFocus,DX,DY,DZ,XAt,YAt,ZAt,Vx,Vy,Vz);

where:

void View::GetProjData(Standard_Real &DX, Standard_Real &DY, Standard_Real &DZ,
Standard_Real &XAt, Standard_Real &YAt, Standard_Real &ZAt,
Standard_Real &Vx, Standard_Real &Vy, Standard_Real &Vz,
Standard_Boolean &IsPerspective,
gp_Pnt &rightBottom, gp_Pnt &leftBottom,
gp_Pnt &leftTop, gp_Pnt &rightTop,
uint sizeX, uint sizeY)
{
myView->Proj(DX,DY,DZ);
myView->At(XAt,YAt,ZAt);
myView->Up(Vx,Vy,Vz);
IsPerspective = (myView->Type() == V3d_PERSPECTIVE);

V3d_Coordinate myV3dX1, myV3dY1, myV3dZ1,
myV3dX2, myV3dY2, myV3dZ2,
myV3dX3, myV3dY3, myV3dZ3,
myV3dX4, myV3dY4, myV3dZ4;

GetCoordFromView(0,0,myV3dX1, myV3dY1, myV3dZ1);
GetCoordFromView(sizeX,0,myV3dX2, myV3dY2, myV3dZ2);
GetCoordFromView(sizeX,sizeY,myV3dX3, myV3dY3, myV3dZ3);
GetCoordFromView(0,sizeY,myV3dX4, myV3dY4, myV3dZ4);

leftTop.SetCoord(myV3dX1, myV3dY1, myV3dZ1);
rightTop.SetCoord(myV3dX2, myV3dY2, myV3dZ2);
rightBottom.SetCoord(myV3dX3, myV3dY3, myV3dZ3);
leftBottom.SetCoord(myV3dX4, myV3dY4, myV3dZ4);

}

It's working for me. Here my sample/

Attachments: 
Mark's picture

The screenshot you provide has more lines in it than what I want: two extras on the near end, one on the far end, one at each T intersection, and a line at each T that would need trimmed (for my purposes, though maybe not for yours).

Unfortunately, it looks like I'd have to rewrite a fair amount of your sample to get it to work for me on linux (no MDIWindow, for example). I can't even find GetCoordFromView in the documentation, so I'm not sure what it's doing.

Using my code, I displayed all of the shapes provided by HLRBRep_HLRToShape. I used a transform on each one so they wouldn't be on top of each other. The only ones that weren't empty were VCompound, OutLineVCompound, and RgNLineVCompound. They are shown in that order (left to right) in the attached image.

Attachments: 
JuryS's picture

I'm use Linux too. And there more problem, because no any help on this forum

void View::GetCoordFromView(const Standard_Integer x, const Standard_Integer y, Standard_Real& X,
Standard_Real& Y,
Standard_Real& Z)
{
V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
myView->Eye(XEye, YEye, ZEye);
myView->At(XAt, YAt, ZAt);
gp_Pnt EyePoint(XEye, YEye, ZEye);
gp_Pnt AtPoint(XAt, YAt, ZAt);

gp_Vec EyeVector(EyePoint, AtPoint);
gp_Dir EyeDir(EyeVector);

gp_Pln PlaneOfTheView(AtPoint, EyeDir);
myView->Convert(x,y,X,Y,Z);
gp_Pnt ConvertedPoint (X,Y,Z);
gp_Pnt2d ConvertedPointOnPlane = ProjLib::Project(PlaneOfTheView,ConvertedPoint);
gp_Pnt ResultPoint = ElSLib::Value(ConvertedPointOnPlane.X(),
ConvertedPointOnPlane.Y(),
PlaneOfTheView);

//qRound âîçâðàùàåò öåëîå çíà÷åíèå, ïîëîæèòåëüíîå èëè îòðèöàòåëüíîå
//abs âîçâðàùàåò öåëîå çíà÷åíèå, òîëüêî îïîëîæèòåëüíîå

//X = qRound(ResultPoint.X());
//Y = qRound(ResultPoint.Y());
//Z = qRound(ResultPoint.Z());
X = ResultPoint.X();
Y = ResultPoint.Y();
Z = ResultPoint.Z();
}

Mark's picture

I confused MDI with MicrobeSoft Foundation Classes, MFC. :-D

I guess I'll try to find a way to remove all of the inner edges, and I'll apply that algo to all of the edges I can get from HLRBRep_HLRToShape.

Thank you
Mark

Tigran's picture

Hi, Mark.

Did you find any solution for that problem ( eliminating the extra inner edges )?

Best regards,
Tigran.

P G's picture

I have also observed with simple boxes too that the corner is shifted to anew location. How to fix that ?
regards - PG

JuryS's picture

Here is new way how to use HLR algo in OCC:

bool DocumentCommon::onHideLines()
{
//1. Make some clean before HLR usage
CleanHideLines();
ShowHatches();

double DX,DY,DZ,XAt,YAt,ZAt,Vx,Vy,Vz,aFocale;
bool IsPerspective;

activeView()->GetProjData(DX,DY,DZ,XAt,YAt,ZAt,Vx,Vy,Vz,IsPerspective,aFocale);

Handle_Prs3d_Projector aPrs3d_Projector = new Prs3d_Projector(IsPerspective,aFocale,DX,DY,DZ,XAt,YAt,ZAt,Vx,Vy,Vz);

Handle_HLRBRep_Algo myHlAlgo = new HLRBRep_Algo();
myHlAlgo->Projector(aPrs3d_Projector->Projector());

AIS_ListOfInteractive aList;
AIS_ListIteratorOfListOfInteractive aListIterator;
myContext->DisplayedObjects(aList);
if (aList.IsEmpty()) return true;

for(aListIterator.Initialize(aList);aListIterator.More();aListIterator.Next())
{
const Handle(AIS_InteractiveObject) &aisShp = aListIterator.Value();

if (aisShp->SelectionMode() != 0) continue; //Some objects don't need to inserted in HLR algo

if (aisShp->Transparency()<0.5) //Objects with transparency don't need to HLR
{

const TopoDS_Shape myShape = Handle(AIS_Shape)::DownCast(aisShp)->Shape();

myHlAlgo->Add(myShape);
}

myContext->SetDisplayMode(aisShp, 2, false); //HIDE object
}

if (!myHlAlgo->Update()) //No face in the shape to hiden (need some fixes in OCC sources)
{
for(aListIterator.Initialize(aList);aListIterator.More();aListIterator.Next())
{
Handle(AIS_InteractiveObject) aisShp = aListIterator.Value();
myContext->SetDisplayMode(aisShp, 0, false); //Display result
}
return true;
}

myHlAlgo->Hide();

HLRAlgo_EdgeIterator myEdgeIterator;

double U1,U2;
BRepAdaptor_Curve TheCurve;

TColgp_SequenceOfPnt Points;

Handle_HLRBRep_Data aDS = myHlAlgo->DataStructure();

if (!aDS.IsNull())
{
for (int i=1;i<=aDS->NbEdges();i++){

myEdgeIterator.InitVisible
(aDS->EDataArray().ChangeValue(i).GetStatus());
while (myEdgeIterator.MoreVisible())
{
aDS->EDataArray().ChangeValue(i);
TheCurve = aDS->EDataArray()
.ChangeValue(i)
.ChangeGeometry()
.Curve();
float t1,t2;
myEdgeIterator.Visible(U1,t1,U2,t2);

StdPrs_DeflectionCurve::Add(aHideLinesPrs,TheCurve,U1,U2,0.02, Points, 0.2,true);

myEdgeIterator.NextVisible();
}

}

}

aHideLinesPrs->Color(Quantity_NOC_BLACK);
aHideLinesPrs->Display();
myContext->UpdateCurrentViewer();

return true;
}