HLR and AIS_ConnectedInteractive

Hello, in my project, I am using AIS_ConnectedInteractive class to have multiple instances of the same TopoDS_Shape appropriately translated and scaled. Everything works fine except for the HLR representation. When I request this type of representation, the ComputeHLR method, which performs the final positioning starting from the connected TopoDS_Shape by multiplying the transformation that defines its position with the transformation applied to AIS_ConnectedInteractive, raises an exception when it generates a new translated and scaled TopoDS_Shape using the "Located" method. The exception is as follows: "Standard_DomainError("Location with scaling transformation is forbidden")." Now, after reading some documentation, it seems that scaling a TopoDS_Shape by applying the scaling transformation to its position is not recommended. Is this a bug, or is there a different way to obtain HLR representation for an AIS_ConnectedInteractive? I'd like to add that this exception was not present in version 7.4.0 of OpenCascade (the previous version I've used), but it is present in the latest version, 7.7.0.

The orginal code of AIS_ConnectedInteractive::ComputeHLR, is the sequent:

void AIS_ConnectedInteractive::computeHLR (const Handle(Graphic3d_Camera)& theProjector,
                                           const Handle(TopLoc_Datum3D)& theTransformation,
                                           const Handle(Prs3d_Presentation)& thePresentation)
{
  const bool hasTrsf = !theTransformation.IsNull()
                     && theTransformation->Form() != gp_Identity;
  updateShape (!hasTrsf);
  if (myShape.IsNull())
  {
    return;
  }
  if (hasTrsf)
  {
    const TopLoc_Location& aLocation = myShape.Location();
   TopoDS_Shape aShape = myShape.Located (TopLoc_Location (theTransformation->Trsf()) * aLocation);
	
	
    AIS_Shape::computeHlrPresentation (theProjector, thePresentation, aShape, myDrawer);
  }
  else
  {
    AIS_Shape::computeHlrPresentation (theProjector, thePresentation, myShape, myDrawer);
  }
}

I've derived a class from AIS_ConnectedInteractive and overridden the ComputeHLR method as follows:

void MyAIS_ConnectedInteractive::computeHLR (const Handle(Graphic3d_Camera)& theProjector,
                                           const Handle(TopLoc_Datum3D)& theTransformation,
                                           const Handle(Prs3d_Presentation)& thePresentation)
{
  const bool hasTrsf = !theTransformation.IsNull()
                     && theTransformation->Form() != gp_Identity;
  updateShape (!hasTrsf);
  if (myShape.IsNull())
  {
    return;
  }
  if (hasTrsf)
  {
    const TopLoc_Location& aLocation = myShape.Location();
    //TopoDS_Shape aShape = myShape.Located (TopLoc_Location (theTransformation->Trsf()) * aLocation);
	TopoDS_Shape aShape = myShape.Located(TopLoc_Location(aLocation));
	BRepBuilderAPI_Transform transform(theTransformation->Trsf());
	transform.Perform(aShape, true, true);
	aShape = transform.Shape();
	
    AIS_Shape::computeHlrPresentation (theProjector, thePresentation, aShape, myDrawer);
  }
  else
  {
    AIS_Shape::computeHlrPresentation (theProjector, thePresentation, myShape, myDrawer);
  }
}

And everything works fine. So I am wondering if this is a bug or if it is due to my incorrect usage of OpenCascade's HLR feature?

gkv311 n's picture

Take a look at OCCT 7.6.0 Release Notes, the section 'Prohibition of scaled transformation within shape location'. Thats why you get this exception.

If your shape already have scale factor - pay attention where this shape comes from, as it may cause failures of some algorithms. Have no idea if particularly HLR algo is known to have such issues.

As for a specific place, you may put extra argument false to TopoDS_Shape::Located() to disarm protection as a workaround, in case if you don't see critical side effects.

Giovanni Pennisi's picture

Thanks for you reply gkv311,

I've read that documentation, indeed in my AIS_ConnectedInteractive derived class, I've overridden the computeHLR method replacing this line:

TopoDS_Shape aShape = myShape.Located (TopLoc_Location (theTransformation->Trsf()) * aLocation);

Whit these ones:

TopoDS_Shape aShape = myShape.Located(TopLoc_Location(aLocation));
BRepBuilderAPI_Transform transform(theTransformation->Trsf());
transform.Perform(aShape, true, true);
aShape = transform.Shape();

Where "theTransformation->Trsf()" is the scale transformation of the AIS_ConnectedInteractive

As specified in OCC 7.6.0 Release notes.

In my code, the scale transformation is applied not within a TopoDS_Shape location but within the transformation of the AIS_ConnectedInteractive. As you can see in the original code of the computeHLR method of AIS_ConnectedInteractive, the exception is raised because the AIS_ConnectedInteractive tranformation is multiplied by the transformation that defines the location of connected TopoDS_Shape and then it is passed to the Located method of the connected TopoDS_Shape:

TopoDS_Shape aShape = myShape.Located (TopLoc_Location (theTransformation->Trsf()) * aLocation);

This means that also the transformation that defines the AIS_ConnectedInteractive should not contain a scale transfomation, according to OCC 7.6.0 releas notes?

gkv311 n's picture

It depends on a robustness of HLR algorithm to such scale factor. On a box it works - don't know if scale factor would cause issues on more complex geometry...

The general idea - yes, to disallow scale in shape location altogether. So that, for instance, if HLR algorithm may handle such transformations robustly, it should expose a dedicated API for that (which it doesn't do for now).

Giovanni Pennisi's picture

Ok, I understand, thanks for the clarification!