\page smeshpy_interface_page Python interface
-Python API for SALOME %Mesh module defines several classes that can
+Python API of SALOME %Mesh module defines several classes that can
be used for easy mesh creation and edition.
-Documentation for SALOME %Mesh module Python API is available in two forms:
+Documentation of SALOME %Mesh module Python API is available in two forms:
- <a href="smeshpy_doc/modules.html">Structured documentation</a>, where all methods and
classes are grouped by their functionality.
- <a href="smeshpy_doc/namespaces.html">Linear documentation</a> grouped only by classes, declared
#include <vtkCellArray.h>
#include <vtkCellData.h>
+#include <vtkLookupTable.h>
#include <vtkObjectFactory.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper2D.h>
+#include <vtkProperty2D.h>
#include <vtkScalarsToColors.h>
#include <vtkTextMapper.h>
#include <vtkTextProperty.h>
#include <vtkViewport.h>
#include <vtkWindow.h>
-#include <vtkLookupTable.h>
-#include <vtkProperty2D.h>
#define SHRINK_COEF 0.08;
// Instantiate object with 64 maximum colors; 5 labels; %%-#6.3g label
// format, no title, and vertical orientation. The initial scalar bar
// size is (0.05 x 0.8) of the viewport size.
-SMESH_ScalarBarActor::SMESH_ScalarBarActor() {
+SMESH_ScalarBarActor::SMESH_ScalarBarActor()
+{
this->LookupTable = NULL;
this->Position2Coordinate->SetValue(0.17, 0.8);
-
+
this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport();
this->PositionCoordinate->SetValue(0.82,0.1);
-
+
this->MaximumNumberOfColors = 64;
this->NumberOfLabels = 5;
this->NumberOfLabelsBuilt = 0;
this->TitleTextProperty = vtkTextProperty::New();
this->TitleTextProperty->ShallowCopy(this->LabelTextProperty);
- this->LabelFormat = new char[8];
+ this->LabelFormat = new char[8];
sprintf(this->LabelFormat,"%s","%-#6.3g");
this->TitleMapper = vtkTextMapper::New();
this->TitleActor->SetMapper(this->TitleMapper);
this->TitleActor->GetPositionCoordinate()->
SetReferenceCoordinate(this->PositionCoordinate);
-
+
this->TextMappers = NULL;
this->TextActors = NULL;
myDistribution = vtkPolyData::New();
myDistributionMapper = vtkPolyDataMapper2D::New();
myDistributionMapper->SetInputData(this->myDistribution);
-
+
myDistributionActor = vtkActor2D::New();
myDistributionActor->SetMapper(this->myDistributionMapper);
myDistributionActor->GetPositionCoordinate()->
{
this->TitleActor->ReleaseGraphicsResources(win);
if (this->TextMappers != NULL )
- {
+ {
for (int i=0; i < this->NumberOfLabelsBuilt; i++)
- {
+ {
this->TextActors[i]->ReleaseGraphicsResources(win);
- }
}
+ }
this->ScalarBarActor->ReleaseGraphicsResources(win);
// rnv begin
// Customization of the vtkScalarBarActor to show distribution histogram.
/*--------------------------------------------------------------------------*/
-SMESH_ScalarBarActor::~SMESH_ScalarBarActor() {
- if (this->LabelFormat)
- {
+SMESH_ScalarBarActor::~SMESH_ScalarBarActor()
+{
+ if (this->LabelFormat)
+ {
delete [] this->LabelFormat;
this->LabelFormat = NULL;
- }
+ }
this->TitleMapper->Delete();
this->TitleActor->Delete();
if (this->TextMappers != NULL )
- {
+ {
for (int i=0; i < this->NumberOfLabelsBuilt; i++)
- {
+ {
this->TextMappers[i]->Delete();
this->TextActors[i]->Delete();
- }
+ }
delete [] this->TextMappers;
delete [] this->TextActors;
- }
+ }
this->ScalarBar->Delete();
this->ScalarBarMapper->Delete();
this->ScalarBarActor->Delete();
if (this->Title)
- {
+ {
delete [] this->Title;
this->Title = NULL;
- }
-
+ }
+
this->SetLookupTable(NULL);
this->SetLabelTextProperty(NULL);
this->SetTitleTextProperty(NULL);
-
+
// rnv begin
// Customization of the vtkScalarBarActor to show distribution histogram:
myDistribution->Delete();
{
int renderedSomething = 0;
int i;
-
+
// Everything is built, just have to render
if (this->Title != NULL)
- {
+ {
renderedSomething += this->TitleActor->RenderOverlay(viewport);
- }
- if (!myTitleOnlyVisibility) {
+ }
+ if ( !myTitleOnlyVisibility ) {
this->ScalarBarActor->RenderOverlay(viewport);
this->myDistributionActor->RenderOverlay(viewport);
- if( this->TextActors == NULL)
- {
- vtkWarningMacro(<<"Need a mapper to render a scalar bar");
- return renderedSomething;
- }
-
- for (i=0; i<this->NumberOfLabels; i++)
- {
+ if ( this->TextActors == NULL )
+ {
+ vtkWarningMacro(<<"Need a mapper to render a scalar bar");
+ return renderedSomething;
+ }
+
+ for ( i=0; i<this->NumberOfLabels; i++ )
+ {
renderedSomething += this->TextActors[i]->RenderOverlay(viewport);
- }
- }
+ }
+ }
renderedSomething = (renderedSomething > 0)?(1):(0);
return renderedSomething;
int renderedSomething = 0;
int i;
int size[2];
-
+
if (!this->LookupTable)
- {
+ {
vtkWarningMacro(<<"Need a mapper to render a scalar bar");
return 0;
- }
+ }
if (!this->TitleTextProperty)
- {
+ {
vtkErrorMacro(<<"Need title text property to render a scalar bar");
return 0;
- }
+ }
if (!this->LabelTextProperty)
- {
+ {
vtkErrorMacro(<<"Need label text property to render a scalar bar");
return 0;
- }
+ }
// Check to see whether we have to rebuild everything
int positionsHaveChanged = 0;
- if (viewport->GetMTime() > this->BuildTime ||
- (viewport->GetVTKWindow() &&
+ if (viewport->GetMTime() > this->BuildTime ||
+ (viewport->GetVTKWindow() &&
viewport->GetVTKWindow()->GetMTime() > this->BuildTime))
- {
+ {
// if the viewport has changed we may - or may not need
// to rebuild, it depends on if the projected coords chage
int *barOrigin;
barOrigin = this->PositionCoordinate->GetComputedViewportValue(viewport);
- size[0] =
+ size[0] =
this->Position2Coordinate->GetComputedViewportValue(viewport)[0] -
barOrigin[0];
- size[1] =
+ size[1] =
this->Position2Coordinate->GetComputedViewportValue(viewport)[1] -
barOrigin[1];
- if (this->LastSize[0] != size[0] ||
+ if (this->LastSize[0] != size[0] ||
this->LastSize[1] != size[1] ||
- this->LastOrigin[0] != barOrigin[0] ||
+ this->LastOrigin[0] != barOrigin[0] ||
this->LastOrigin[1] != barOrigin[1])
- {
+ {
positionsHaveChanged = 1;
- }
}
-
+ }
+
// Check to see whether we have to rebuild everything
- if (positionsHaveChanged ||
- this->GetMTime() > this->BuildTime ||
- this->LookupTable->GetMTime() > this->BuildTime ||
- this->LabelTextProperty->GetMTime() > this->BuildTime ||
- this->TitleTextProperty->GetMTime() > this->BuildTime)
- {
+ if ( positionsHaveChanged ||
+ this->GetMTime() > this->BuildTime ||
+ this->LookupTable->GetMTime() > this->BuildTime ||
+ this->LabelTextProperty->GetMTime() > this->BuildTime ||
+ this->TitleTextProperty->GetMTime() > this->BuildTime)
+ {
vtkDebugMacro(<<"Rebuilding subobjects");
// Delete previously constructed objects
//
- if (this->TextMappers != NULL )
+ if ( this->TextMappers != NULL )
+ {
+ for ( i = 0; i < this->NumberOfLabelsBuilt; i++ )
{
- for (i=0; i < this->NumberOfLabelsBuilt; i++)
- {
this->TextMappers[i]->Delete();
this->TextActors[i]->Delete();
- }
+ }
delete [] this->TextMappers;
delete [] this->TextActors;
- }
+ }
// Build scalar bar object; determine its type
//
- // is this a vtkLookupTable or a subclass of vtkLookupTable
+ // is this a vtkLookupTable or a subclass of vtkLookupTable
// with its scale set to log
// NOTE: it's possible we could to without the 'lut' variable
// later in the code, but if the vtkLookupTableSafeDownCast operation
vtkLookupTable *LUT = vtkLookupTable::SafeDownCast( this->LookupTable );
int isLogTable = 0;
if ( LUT )
- {
+ {
if ( LUT->GetScale() == VTK_SCALE_LOG10 )
- {
- isLogTable = 1;
- }
+ {
+ isLogTable = 1;
}
-
+ }
+
// we hard code how many steps to display
vtkScalarsToColors *lut = this->LookupTable;
int numColors = this->MaximumNumberOfColors;
if(!distrVisibility)
vtkDebugMacro(<<" Distribution invisible, because numColors == this->myNbValues.size()");
- if ( distrVisibility && GetDistributionVisibility() ) {
+ if ( distrVisibility && GetDistributionVisibility() )
+ {
for ( i = 0 ; i < (int)myNbValues.size(); i++ ) {
if ( myNbValues[i] ) {
numPositiveVal++;
this->myDistribution->SetPolys(distrPolys);
distrPts->Delete();
distrPolys->Delete();
- if ( myDistributionColoringType == SMESH_MULTICOLOR_TYPE ) {
+ if ( myDistributionColoringType == SMESH_MULTICOLOR_TYPE )
+ {
distColors = vtkUnsignedCharArray::New();
distColors->SetNumberOfComponents(3);
distColors->SetNumberOfTuples(numPositiveVal);
this->myDistribution->GetCellData()->SetScalars(distColors);
distColors->Delete();
- } else if( myDistributionColoringType == SMESH_MONOCOLOR_TYPE ){
+ }
+ else if( myDistributionColoringType == SMESH_MONOCOLOR_TYPE )
+ {
this->myDistribution->GetCellData()->SetScalars(NULL);
}
- } else {
+ }
+ else
+ {
myDistribution->Reset();
}
// rnv end
// get the viewport size in display coordinates
int *barOrigin, barWidth, barHeight, distrHeight;
barOrigin = this->PositionCoordinate->GetComputedViewportValue(viewport);
- size[0] =
+ size[0] =
this->Position2Coordinate->GetComputedViewportValue(viewport)[0] -
barOrigin[0];
- size[1] =
+ size[1] =
this->Position2Coordinate->GetComputedViewportValue(viewport)[1] -
barOrigin[1];
this->LastOrigin[0] = barOrigin[0];
this->LastOrigin[1] = barOrigin[1];
this->LastSize[0] = size[0];
this->LastSize[1] = size[1];
-
+
// Update all the composing objects
this->TitleActor->SetProperty(this->GetProperty());
this->TitleMapper->SetInput(this->Title);
if (this->TitleTextProperty->GetMTime() > this->BuildTime)
- {
+ {
// Shallow copy here so that the size of the title prop is not affected
// by the automatic adjustment of its text mapper's size (i.e. its
// mapper's text property is identical except for the font size
// the title and label text prop to be the same.
this->TitleMapper->GetTextProperty()->ShallowCopy(this->TitleTextProperty);
this->TitleMapper->GetTextProperty()->SetJustificationToCentered();
- }
-
+ }
+
// find the best size for the title font
int titleSize[2];
this->SizeTitle(titleSize, size, viewport);
-
+
// find the best size for the ticks
int labelSize[2];
this->AllocateAndSizeLabels(labelSize, size, viewport,range);
this->NumberOfLabelsBuilt = this->NumberOfLabels;
-
+
// generate points
double x[3]; x[2] = 0.0;
double delta, itemH, shrink;
barHeight = (int)(0.86*size[1]);
delta=(double)barHeight/numColors;
-
+
for ( i=0; i<numPts/2; i++ ) {
x[0] = distrHeight+delimeter/2.0;
x[1] = i*delta;
pts->SetPoint(2*i+1,x);
}
- if(GetDistributionVisibility() && distrVisibility) {
- // Distribution points
+ if ( GetDistributionVisibility() && distrVisibility ) {
+ // Distribution points
shrink = delta*SHRINK_COEF;
vtkIdType distPtsId=0;
vtkIdType distPtsIds[4];
- for(i=0; i<numColors; i++) {
- if(myNbValues[i]) {
+ for ( i = 0; i < numColors; i++ ) {
+ if ( myNbValues[i] ) {
itemH = distrHeight*((double)myNbValues[i]/maxValue);
-
- if(distrHeight == itemH)
+
+ if(distrHeight == itemH)
itemH = itemH - delimeter/2;
x[1] = i*delta+shrink;
// first point of polygon (quadrangle)
- x[0] = 0;
+ x[0] = 0;
distPtsIds[0] = distPtsId;
distrPts->SetPoint(distPtsId++,x);
x[1] = i*delta+delta-shrink;
// third point of polygon (quadrangle)
- x[0] = 0;
+ x[0] = 0;
distPtsIds[3] = distPtsId;
distrPts->SetPoint(distPtsId++,x);
distrPolys->InsertNextCell(4,distPtsIds);
}
}
- }
+ }
}
// rnv end
else {
barWidth = size[0];
-
+
// rnv begin
// Customization of the vtkScalarBarActor to show distribution histogram.
double coef1, delimeter=0.0;
- if(GetDistributionVisibility() && distrVisibility) {
+ if ( GetDistributionVisibility() && distrVisibility ) {
coef1=0.62;
distrHeight = (int)((coef1/2)*size[1]);
- //delimeter between distribution diagram and scalar bar
+ //delimeter between distribution diagram and scalar bar
delimeter=0.02*size[1];
}
else {
barHeight = (int)(coef1*size[1]);
distrHeight = 0;
}
-
+
barHeight = (int)(coef1*size[1]);
-
+
delta=(double)barWidth/numColors;
- for (i=0; i<numPts/2; i++) {
+ for ( i = 0; i < numPts/2; i++ ) {
x[0] = i*delta;
x[1] = barHeight;
- pts->SetPoint(2*i,x);
+ pts->SetPoint(2*i,x);
x[1] = distrHeight + delimeter;
pts->SetPoint(2*i+1,x);
}
-
- if(GetDistributionVisibility() && distrVisibility) {
- // Distribution points
+
+ if ( GetDistributionVisibility() && distrVisibility ) {
+ // Distribution points
shrink = delta*SHRINK_COEF;
vtkIdType distPtsId=0;
vtkIdType distPtsIds[4];
- for(i=0; i<numColors; i++) {
+ for ( i = 0; i < numColors; i++ ) {
if(myNbValues[i]) {
itemH = distrHeight*((double)myNbValues[i]/maxValue);
-
+
// first point of polygon (quadrangle)
- x[0] = i*delta+shrink;
+ x[0] = i*delta+shrink;
x[1] = 0;
distPtsIds[0] = distPtsId;
distrPts->SetPoint(distPtsId++,x);
-
+
// second point of polygon (quadrangle)
- x[0] = i*delta+shrink;
+ x[0] = i*delta+shrink;
x[1] = itemH;
distPtsIds[3] = distPtsId;
distrPts->SetPoint(distPtsId++,x);
-
+
// third point of polygon (quadrangle)
- x[0] = i*delta+delta-shrink;
+ x[0] = i*delta+delta-shrink;
x[1] = 0;
distPtsIds[1] = distPtsId;
distrPts->SetPoint(distPtsId++,x);
-
+
// fourth point of polygon (quadrangle)
- x[0] = i*delta+delta-shrink;
+ x[0] = i*delta+delta-shrink;
x[1] = itemH;
distPtsIds[2] = distPtsId;
distrPts->SetPoint(distPtsId++,x);
-
+
// Add polygon into poly data
distrPolys->InsertNextCell(4,distPtsIds);
}
- }
+ }
}
// rnv end
}
-
+
//polygons & cell colors
unsigned char *rgba, *rgb;
vtkIdType ptIds[4], dcCount=0;
- for (i=0; i<numColors; i++)
- {
+ for ( i = 0; i < numColors; i++ )
+ {
ptIds[0] = 2*i;
ptIds[1] = ptIds[0] + 1;
ptIds[2] = ptIds[1] + 2;
polys->InsertNextCell(4,ptIds);
if ( isLogTable )
- {
- double rgbval = log10(range[0]) +
+ {
+ double rgbval = log10(range[0]) +
i*(log10(range[1])-log10(range[0]))/(numColors -1);
rgba = lut->MapValue(pow(10.0,rgbval));
- }
+ }
else
- {
+ {
rgba = lut->MapValue(range[0] + (range[1] - range[0])*
((double)i /(numColors-1.0)));
- }
+ }
rgb = colors->GetPointer(3*i); //write into array directly
rgb[0] = rgba[0];
rgb[1] = rgba[1];
rgb[2] = rgba[2];
-
+
// rnv begin
// Customization of the vtkScalarBarActor to show distribution histogram.
- if(myDistributionColoringType == SMESH_MULTICOLOR_TYPE && GetDistributionVisibility() && distrVisibility)
- {
- rgb = distColors->GetPointer(3*dcCount); //write into array directly
- rgb[0] = rgba[0];
- rgb[1] = rgba[1];
- rgb[2] = rgba[2];
- dcCount++;
- }
+ if ( myDistributionColoringType == SMESH_MULTICOLOR_TYPE &&
+ GetDistributionVisibility() &&
+ distrVisibility )
+ {
+ rgb = distColors->GetPointer(3*dcCount); //write into array directly
+ rgb[0] = rgba[0];
+ rgb[1] = rgba[1];
+ rgb[2] = rgba[2];
+ dcCount++;
}
+ }
// Now position everything properly
//
double val;
- if (this->Orientation == VTK_ORIENT_VERTICAL)
- {
+ if ( this->Orientation == VTK_ORIENT_VERTICAL )
+ {
int sizeTextData[2];
-
+
// center the title
this->TitleActor->SetPosition(size[0]/2, 0.9*size[1]);
-
- for (i=0; i < this->NumberOfLabels; i++)
+
+ for ( i = 0; i < this->NumberOfLabels; i++ )
+ {
+ if ( this->NumberOfLabels > 1 )
{
- if (this->NumberOfLabels > 1)
- {
val = (double)i/(this->NumberOfLabels-1) *barHeight;
- }
- else
- {
+ }
+ else
+ {
val = 0.5*barHeight;
- }
+ }
this->TextMappers[i]->GetSize(viewport,sizeTextData);
this->TextMappers[i]->GetTextProperty()->SetJustificationToLeft();
this->TextActors[i]->SetPosition(barWidth+3,
val - sizeTextData[1]/2);
- }
}
+ }
else
- {
- this->TitleActor->SetPosition(size[0]/2,
+ {
+ this->TitleActor->SetPosition(size[0]/2,
barHeight + labelSize[1] + 0.1*size[1]);
- for (i=0; i < this->NumberOfLabels; i++)
- {
+ for ( i = 0; i < this->NumberOfLabels; i++ )
+ {
this->TextMappers[i]->GetTextProperty()->SetJustificationToCentered();
if (this->NumberOfLabels > 1)
- {
+ {
val = (double)i/(this->NumberOfLabels-1) * barWidth;
- }
+ }
else
- {
+ {
val = 0.5*barWidth;
- }
- this->TextActors[i]->SetPosition(val, barHeight + 0.05*size[1]);
}
+ this->TextActors[i]->SetPosition(val, barHeight + 0.05*size[1]);
}
+ }
this->BuildTime.Modified();
- }
+ }
// Everything is built, just have to render
- if (this->Title != NULL)
- {
+ if ( this->Title != NULL )
+ {
renderedSomething += this->TitleActor->RenderOpaqueGeometry(viewport);
- }
+ }
this->ScalarBarActor->RenderOpaqueGeometry(viewport);
this->myDistributionActor->RenderOpaqueGeometry(viewport);
- for (i=0; i<this->NumberOfLabels; i++)
- {
+ for ( i = 0; i < this->NumberOfLabels; i++ )
+ {
renderedSomething += this->TextActors[i]->RenderOpaqueGeometry(viewport);
- }
+ }
renderedSomething = (renderedSomething > 0)?(1):(0);
this->Superclass::PrintSelf(os,indent);
if ( this->LookupTable )
- {
+ {
os << indent << "Lookup Table:\n";
this->LookupTable->PrintSelf(os,indent.GetNextIndent());
- }
+ }
else
- {
+ {
os << indent << "Lookup Table: (none)\n";
- }
+ }
if (this->TitleTextProperty)
- {
+ {
os << indent << "Title Text Property:\n";
this->TitleTextProperty->PrintSelf(os,indent.GetNextIndent());
- }
+ }
else
- {
+ {
os << indent << "Title Text Property: (none)\n";
- }
+ }
if (this->LabelTextProperty)
- {
+ {
os << indent << "Label Text Property:\n";
this->LabelTextProperty->PrintSelf(os,indent.GetNextIndent());
- }
+ }
else
- {
+ {
os << indent << "Label Text Property: (none)\n";
- }
+ }
os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n";
- os << indent << "Maximum Number Of Colors: "
+ os << indent << "Maximum Number Of Colors: "
<< this->MaximumNumberOfColors << "\n";
os << indent << "Number Of Labels: " << this->NumberOfLabels << "\n";
os << indent << "Number Of Labels Built: " << this->NumberOfLabelsBuilt << "\n";
os << indent << "Orientation: ";
if ( this->Orientation == VTK_ORIENT_HORIZONTAL )
- {
+ {
os << "Horizontal\n";
- }
+ }
else
- {
+ {
os << "Vertical\n";
- }
+ }
os << indent << "Label Format: " << this->LabelFormat << "\n";
}
{
SMESH_ScalarBarActor *a = SMESH_ScalarBarActor::SafeDownCast(prop);
if ( a != NULL )
- {
+ {
this->SetPosition2(a->GetPosition2());
this->SetLookupTable(a->GetLookupTable());
this->SetMaximumNumberOfColors(a->GetMaximumNumberOfColors());
this->SetTitleTextProperty(a->GetTitleTextProperty());
this->SetLabelFormat(a->GetLabelFormat());
this->SetTitle(a->GetTitle());
- this->GetPositionCoordinate()->SetCoordinateSystem(
- a->GetPositionCoordinate()->GetCoordinateSystem());
- this->GetPositionCoordinate()->SetValue(
- a->GetPositionCoordinate()->GetValue());
- this->GetPosition2Coordinate()->SetCoordinateSystem(
- a->GetPosition2Coordinate()->GetCoordinateSystem());
- this->GetPosition2Coordinate()->SetValue(
- a->GetPosition2Coordinate()->GetValue());
- }
+ this->GetPositionCoordinate()->SetCoordinateSystem
+ (a->GetPositionCoordinate()->GetCoordinateSystem());
+ this->GetPositionCoordinate()->SetValue
+ (a->GetPositionCoordinate()->GetValue());
+ this->GetPosition2Coordinate()->SetCoordinateSystem
+ (a->GetPosition2Coordinate()->GetCoordinateSystem());
+ this->GetPosition2Coordinate()->SetValue
+ (a->GetPosition2Coordinate()->GetValue());
+ }
// Now do superclass
this->vtkActor2D::ShallowCopy(prop);
}
//----------------------------------------------------------------------------
-void SMESH_ScalarBarActor::AllocateAndSizeLabels(int *labelSize,
- int *size,
- vtkViewport *viewport,
- double *range)
+void SMESH_ScalarBarActor::AllocateAndSizeLabels(int *labelSize,
+ int *size,
+ vtkViewport *viewport,
+ double *range)
{
labelSize[0] = labelSize[1] = 0;
double val;
int i;
-
+
// TODO: this should be optimized, maybe by keeping a list of
// allocated mappers, in order to avoid creation/destruction of
// their underlying text properties (i.e. each time a mapper is
// created, text properties are created and shallow-assigned a font size
// which value might be "far" from the target font size).
- // is this a vtkLookupTable or a subclass of vtkLookupTable
+ // is this a vtkLookupTable or a subclass of vtkLookupTable
// with its scale set to log
vtkLookupTable *LUT = vtkLookupTable::SafeDownCast( this->LookupTable );
int isLogTable = 0;
if ( LUT )
- {
+ {
if ( LUT->GetScale() == VTK_SCALE_LOG10 )
- {
- isLogTable = 1;
- }
+ {
+ isLogTable = 1;
}
+ }
- for (i=0; i < this->NumberOfLabels; i++)
- {
+ for ( i = 0; i < this->NumberOfLabels; i++ )
+ {
this->TextMappers[i] = vtkTextMapper::New();
if ( isLogTable )
- {
+ {
double lval;
- if (this->NumberOfLabels > 1)
- {
+ if ( this->NumberOfLabels > 1 )
+ {
lval = log10(range[0]) + (double)i/(this->NumberOfLabels-1) *
(log10(range[1])-log10(range[0]));
- }
+ }
else
- {
+ {
lval = log10(range[0]) + 0.5*(log10(range[1])-log10(range[0]));
- }
- val = pow(10.0,lval);
}
+ val = pow(10.0,lval);
+ }
else
+ {
+ if ( this->NumberOfLabels > 1 )
{
- if (this->NumberOfLabels > 1)
- {
- val = range[0] +
+ val = range[0] +
(double)i/(this->NumberOfLabels-1) * (range[1]-range[0]);
- }
+ }
else
- {
+ {
val = range[0] + 0.5*(range[1]-range[0]);
- }
}
+ }
sprintf(string, this->LabelFormat, val);
this->TextMappers[i]->SetInput(string);
// which will be modified later). This allows text actors to
// share the same text property, and in that case specifically allows
// the title and label text prop to be the same.
- this->TextMappers[i]->GetTextProperty()->ShallowCopy(
- this->LabelTextProperty);
+ this->TextMappers[i]->GetTextProperty()->ShallowCopy(this->LabelTextProperty);
this->TextActors[i] = vtkActor2D::New();
this->TextActors[i]->SetMapper(this->TextMappers[i]);
this->TextActors[i]->SetProperty(this->GetProperty());
this->TextActors[i]->GetPositionCoordinate()->
SetReferenceCoordinate(this->PositionCoordinate);
- }
+ }
- if (this->NumberOfLabels)
- {
+ if ( this->NumberOfLabels )
+ {
int targetWidth, targetHeight;
// rnv begin
// Customization of the vtkScalarBarActor to show distribution histogram.
bool distrVisibility = ( this->MaximumNumberOfColors == (int) this->myNbValues.size() );
double coef;
- if( GetDistributionVisibility() && distrVisibility )
- if(this->Orientation == VTK_ORIENT_VERTICAL)
+ if ( GetDistributionVisibility() && distrVisibility )
+ if ( this->Orientation == VTK_ORIENT_VERTICAL )
coef = 0.4;
- else
+ else
coef = 0.18;
- else
- if(this->Orientation == VTK_ORIENT_VERTICAL)
+ else
+ if (this->Orientation == VTK_ORIENT_VERTICAL )
coef = 0.6;
- else
+ else
coef=0.25;
if ( this->Orientation == VTK_ORIENT_VERTICAL )
- {
+ {
targetWidth = (int)(coef*size[0]);
targetHeight = (int)(0.86*size[1]/this->NumberOfLabels);
- }
+ }
else
- {
+ {
targetWidth = (int)(size[0]*0.8/this->NumberOfLabels);
targetHeight = (int)(coef*size[1]);
- }
- // rnv end
-
- vtkTextMapper::SetMultipleConstrainedFontSize(viewport,
- targetWidth,
- targetHeight,
- this->TextMappers,
- this->NumberOfLabels,
- labelSize);
}
+ // rnv end
+
+ vtkTextMapper::SetMultipleConstrainedFontSize( viewport,
+ targetWidth,
+ targetHeight,
+ this->TextMappers,
+ this->NumberOfLabels,
+ labelSize );
+ }
}
//----------------------------------------------------------------------------
-void SMESH_ScalarBarActor::SizeTitle(int *titleSize,
- int *size,
+void SMESH_ScalarBarActor::SizeTitle(int *titleSize,
+ int *size,
vtkViewport *viewport)
{
titleSize[0] = titleSize[1] = 0;
- if (this->Title == NULL || !strlen(this->Title))
+ if ( this->Title == NULL || !strlen(this->Title) )
{
return;
}
/*--------------------------------------------------------------------------*/
-void SMESH_ScalarBarActor::SetDistributionVisibility(int flag) {
- myDistributionActor->SetVisibility(flag);
+void SMESH_ScalarBarActor::SetDistributionVisibility( int flag )
+{
+ myDistributionActor->SetVisibility( flag );
Modified();
}
/*--------------------------------------------------------------------------*/
-int SMESH_ScalarBarActor::GetDistributionVisibility() {
+int SMESH_ScalarBarActor::GetDistributionVisibility()
+{
return myDistributionActor->GetVisibility();
}
-void SMESH_ScalarBarActor::SetDistribution(std::vector<int> theNbValues) {
+void SMESH_ScalarBarActor::SetDistribution( const std::vector<int>& theNbValues )
+{
myNbValues = theNbValues;
-}
+}
-void SMESH_ScalarBarActor::SetDistributionColor (double rgb[3]) {
+void SMESH_ScalarBarActor::SetDistributionColor( double rgb[3] )
+{
myDistributionActor->GetProperty()->SetColor(rgb);
Modified();
}
-void SMESH_ScalarBarActor::GetDistributionColor (double rgb[3]) {
+void SMESH_ScalarBarActor::GetDistributionColor( double rgb[3] )
+{
myDistributionActor->GetProperty()->GetColor(rgb);
}
-void SMESH_ScalarBarActor::SetTitleOnlyVisibility( bool theTitleOnlyVisibility) {
+void SMESH_ScalarBarActor::SetTitleOnlyVisibility( bool theTitleOnlyVisibility )
+{
myTitleOnlyVisibility = theTitleOnlyVisibility;
}
-bool SMESH_ScalarBarActor::GetTitleOnlyVisibility() {
+bool SMESH_ScalarBarActor::GetTitleOnlyVisibility()
+{
return myTitleOnlyVisibility;
}
virtual int GetDistributionVisibility();
// Description:
// Set distribution
- virtual void SetDistribution(std::vector<int> theNbValues);
+ virtual void SetDistribution(const std::vector<int>& theNbValues);
// Description:
// Set distribution coloring type (SMESH_MONOCOLOR_TYPE or SMESH_MULTICOLOR_TYPE)
hl->addWidget( nb0DElemsLab, 0, 1 );
my0DElemsTB->setEnabled( nbElements );
nb0DElemsLab->setEnabled( nbElements );
- myNbTypes += ( nbElements > 0 );
+ myNbTypes = ( nbElements > 0 );
// Edges
nbElements = myActor ? myActor->GetObject()->GetNbEntities( SMDSAbs_Edge ) : aMesh->NbEdges();
#include "StdMeshers_ProjectionUtils.hxx"
#include "SMDS_EdgePosition.hxx"
+#include "SMDS_FacePosition.hxx"
#include "SMESHDS_Mesh.hxx"
#include "SMESH_Algo.hxx"
#include "SMESH_Block.hxx"
#include "utilities.h"
#include <BRepAdaptor_Surface.hxx>
+#include <BRepMesh_Delaun.hxx>
#include <BRepTools.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <BRep_Builder.hxx>
}
return true;
}
-}
+
+ //================================================================================
+ /*!
+ * \brief Add in-FACE nodes surrounding a given node to a queue
+ */
+ //================================================================================
+
+ typedef list< pair< const SMDS_MeshNode*, const BRepMesh_Triangle* > > TNodeTriaList;
+
+ void addCloseNodes( const SMDS_MeshNode* srcNode,
+ const BRepMesh_Triangle* bmTria,
+ const int srcFaceID,
+ TNodeTriaList & noTriQueue )
+ {
+ // find in-FACE nodes
+ SMDS_ElemIteratorPtr elems = srcNode->GetInverseElementIterator(SMDSAbs_Face);
+ while ( elems->more() )
+ {
+ const SMDS_MeshElement* elem = elems->next();
+ if ( elem->getshapeId() == srcFaceID )
+ {
+ for ( int i = 0, nb = elem->NbNodes(); i < nb; ++i )
+ {
+ const SMDS_MeshNode* n = elem->GetNode( i );
+ if ( !n->isMarked() )
+ noTriQueue.push_back( make_pair( n, bmTria ));
+ }
+ }
+ }
+ }
+
+ //================================================================================
+ /*!
+ * \brief Find a delauney triangle containing a given 2D point and return
+ * barycentric coordinates within the found triangle
+ */
+ //================================================================================
+
+ const BRepMesh_Triangle* findTriangle( const gp_XY& uv,
+ const BRepMesh_Triangle* bmTria,
+ Handle(BRepMesh_DataStructureOfDelaun)& triaDS,
+ double bc[3] )
+ {
+ int nodeIDs[3];
+ gp_XY nodeUVs[3];
+ int linkIDs[3];
+ Standard_Boolean ori[3];
+
+ while ( bmTria )
+ {
+ // check bmTria
+
+ triaDS->ElementNodes( *bmTria, nodeIDs );
+ nodeUVs[0] = triaDS->GetNode( nodeIDs[0] ).Coord();
+ nodeUVs[1] = triaDS->GetNode( nodeIDs[1] ).Coord();
+ nodeUVs[2] = triaDS->GetNode( nodeIDs[2] ).Coord();
+
+ SMESH_MeshAlgos::GetBarycentricCoords( uv,
+ nodeUVs[0], nodeUVs[1], nodeUVs[2],
+ bc[0], bc[1] );
+ if ( bc[0] >= 0 && bc[1] >= 0 && bc[0] + bc[1] <= 1 )
+ {
+ bc[2] = 1 - bc[0] - bc[1];
+ return bmTria;
+ }
+
+ // look for a neighbor triangle, which is adjacent to a link intersected
+ // by a segment( triangle center -> uv )
+
+ gp_XY gc = ( nodeUVs[0] + nodeUVs[1] + nodeUVs[2] ) / 3.;
+ gp_XY seg = uv - gc;
+
+ bmTria->Edges( linkIDs, ori );
+ int triaID = triaDS->IndexOf( *bmTria );
+ bmTria = 0;
+
+ for ( int i = 0; i < 3; ++i )
+ {
+ const BRepMesh_PairOfIndex & triIDs = triaDS->ElementsConnectedTo( linkIDs[i] );
+ if ( triIDs.Extent() < 2 )
+ continue; // no neighbor triangle
+
+ // check if a link intersects gc2uv
+ const BRepMesh_Edge & link = triaDS->GetLink( linkIDs[i] );
+ const BRepMesh_Vertex & n1 = triaDS->GetNode( link.FirstNode() );
+ const BRepMesh_Vertex & n2 = triaDS->GetNode( link.LastNode() );
+ gp_XY uv1 = n1.Coord();
+ gp_XY lin = n2.Coord() - uv1; // link direction
+
+ double crossSegLin = seg ^ lin;
+ if ( Abs( crossSegLin ) < std::numeric_limits<double>::min() )
+ continue; // parallel
+
+ double uSeg = ( uv1 - gc ) ^ lin / crossSegLin;
+ if ( 0. <= uSeg && uSeg <= 1. )
+ {
+ bmTria = & triaDS->GetElement( triIDs.Index( 1 + ( triIDs.Index(1) == triaID )));
+ break;
+ }
+ }
+ }
+ return bmTria;
+ }
+
+ //================================================================================
+ /*!
+ * \brief triangulate the srcFace in 2D
+ * \param [in] srcWires - boundary of the src FACE
+ */
+ //================================================================================
+
+ Morph::Morph(const TSideVector& srcWires)
+ {
+ _srcSubMesh = srcWires[0]->GetMesh()->GetSubMesh( srcWires[0]->Face() );
+
+ // compute _scale
+ {
+ BRepAdaptor_Surface surf( srcWires[0]->Face() );
+ const int nbDiv = 100;
+ const double uRange = surf.LastUParameter() - surf.FirstUParameter();
+ const double vRange = surf.LastVParameter() - surf.FirstVParameter();
+ const double dU = uRange / nbDiv;
+ const double dV = vRange / nbDiv;
+ double u = surf.FirstUParameter(), v = surf.FirstVParameter();
+ gp_Pnt p0U = surf.Value( u, v ), p0V = p0U;
+ double lenU = 0, lenV = 0;
+ for ( ; u < surf.LastUParameter(); u += dU, v += dV )
+ {
+ gp_Pnt p1U = surf.Value( u, surf.FirstVParameter() );
+ lenU += p1U.Distance( p0U );
+ p0U = p1U;
+ gp_Pnt p1V = surf.Value( surf.FirstUParameter(), v );
+ lenV += p1V.Distance( p0V );
+ p0V = p1V;
+ }
+ _scale.SetCoord( lenU / uRange, lenV / vRange );
+ }
+
+ // count boundary points
+ int iP = 1, nbP = 0;
+ for ( size_t iW = 0; iW < srcWires.size(); ++iW )
+ nbP += srcWires[iW]->NbPoints() - 1; // 1st and last points coincide
+
+ _bndSrcNodes.resize( nbP + 1 ); _bndSrcNodes[0] = 0;
+
+ // fill boundary points
+ BRepMesh::Array1OfVertexOfDelaun srcVert( 1, 1 + nbP );
+ BRepMesh_Vertex v( 0, 0, BRepMesh_Frontier );
+ for ( size_t iW = 0; iW < srcWires.size(); ++iW )
+ {
+ const UVPtStructVec& srcPnt = srcWires[iW]->GetUVPtStruct();
+ for ( int i = 0, nb = srcPnt.size() - 1; i < nb; ++i, ++iP )
+ {
+ _bndSrcNodes[ iP ] = srcPnt[i].node;
+ srcPnt[i].node->setIsMarked( true );
+
+ v.ChangeCoord() = srcPnt[i].UV().Multiplied( _scale );
+ srcVert( iP ) = v;
+ }
+ }
+ // triangulate the srcFace in 2D
+ BRepMesh_Delaun delauney( srcVert );
+ _triaDS = delauney.Result();
+ }
+
+ //================================================================================
+ /*!
+ * \brief Move non-marked target nodes
+ * \param [in,out] tgtHelper - helper
+ * \param [in] tgtWires - boundary nodes of the target FACE; must be in the
+ * same order as the nodes in srcWires given in the constructor
+ * \param [in] src2tgtNodes - map of src -> tgt nodes
+ * \param [in] moveAll - to move all nodes; if \c false, move only non-marked nodes
+ * \return bool - Ok or not
+ */
+ //================================================================================
+
+ bool Morph::Perform(SMESH_MesherHelper& tgtHelper,
+ const TSideVector& tgtWires,
+ Handle(ShapeAnalysis_Surface) tgtSurface,
+ const TNodeNodeMap& src2tgtNodes,
+ const bool moveAll)
+ {
+ // get tgt boundary points corresponding to _bndSrcNodes
+ size_t nbP = 0;
+ for ( size_t iW = 0; iW < tgtWires.size(); ++iW )
+ nbP += tgtWires[iW]->NbPoints() - 1; // 1st and last points coincide
+ if ( nbP != _bndSrcNodes.size() - 1 )
+ return false;
+
+ BRepMesh::Array1OfVertexOfDelaun tgtVert( 1, 1 + nbP );
+ BRepMesh_Vertex v( 0, 0, BRepMesh_Frontier );
+ for ( size_t iW = 0, iP = 1; iW < tgtWires.size(); ++iW )
+ {
+ const UVPtStructVec& tgtPnt = tgtWires[iW]->GetUVPtStruct();
+ for ( int i = 0, nb = tgtPnt.size() - 1; i < nb; ++i, ++iP )
+ {
+ v.ChangeCoord() = tgtPnt[i].UV().Multiplied( _scale );
+ tgtVert( iP ) = v;
+ }
+ }
+
+ const TopoDS_Face& srcFace = TopoDS::Face( _srcSubMesh->GetSubShape() );
+ const int srcFaceID = _srcSubMesh->GetId();
+ SMESHDS_Mesh* tgtMesh = tgtHelper.GetMeshDS();
+ const SMDS_MeshNode *srcNode, *tgtNode;
+ const BRepMesh_Triangle *bmTria;
+
+ // initialize a queue of nodes with starting triangles
+ TNodeTriaList noTriQueue;
+ size_t iBndSrcN = 1;
+ for ( ; iBndSrcN < _bndSrcNodes.size() && noTriQueue.empty(); ++iBndSrcN )
+ {
+ // get a triangle
+ const BRepMesh::ListOfInteger & linkIds = _triaDS->LinksConnectedTo( iBndSrcN );
+ const BRepMesh_PairOfIndex & triaIds = _triaDS->ElementsConnectedTo( linkIds.First() );
+ const BRepMesh_Triangle& tria = _triaDS->GetElement( triaIds.Index(1) );
+
+ addCloseNodes( _bndSrcNodes[ iBndSrcN ], &tria, srcFaceID, noTriQueue );
+ }
+
+ // un-mark internal src nodes; later we will mark moved nodes
+ int nbSrcNodes = 0;
+ SMDS_NodeIteratorPtr nIt = _srcSubMesh->GetSubMeshDS()->GetNodes();
+ if ( !nIt || !nIt->more() ) return true;
+ if ( moveAll )
+ {
+ nbSrcNodes = _srcSubMesh->GetSubMeshDS()->NbNodes();
+ while ( nIt->more() )
+ nIt->next()->setIsMarked( false );
+ }
+ else
+ {
+ while ( nIt->more() )
+ nbSrcNodes += int( !nIt->next()->isMarked() );
+ }
+
+ // Move tgt nodes
+
+ double bc[3]; // barycentric coordinates
+ int nodeIDs[3];
+ bool checkUV = true;
+ const SMDS_FacePosition* pos;
+
+ while ( nbSrcNodes > 0 )
+ {
+ while ( !noTriQueue.empty() )
+ {
+ srcNode = noTriQueue.front().first;
+ bmTria = noTriQueue.front().second;
+ noTriQueue.pop_front();
+ if ( srcNode->isMarked() )
+ continue;
+ --nbSrcNodes;
+ srcNode->setIsMarked( true );
+
+ // find a delauney triangle containing the src node
+ gp_XY uv = tgtHelper.GetNodeUV( srcFace, srcNode, NULL, &checkUV );
+ uv *= _scale;
+ bmTria = findTriangle( uv, bmTria, _triaDS, bc );
+ if ( !bmTria )
+ continue;
+
+ // compute new coordinates for a corresponding tgt node
+ gp_XY uvNew( 0., 0. ), nodeUV;
+ _triaDS->ElementNodes( *bmTria, nodeIDs );
+ for ( int i = 0; i < 3; ++i )
+ uvNew += bc[i] * tgtVert( nodeIDs[i]).Coord();
+ uvNew.SetCoord( uvNew.X() / _scale.X(), uvNew.Y() / _scale.Y() );
+ gp_Pnt xyz = tgtSurface->Value( uvNew );
+
+ // find and move tgt node
+ TNodeNodeMap::const_iterator n2n = src2tgtNodes.find( srcNode );
+ if ( n2n == src2tgtNodes.end() ) continue;
+ tgtNode = n2n->second;
+ tgtMesh->MoveNode( tgtNode, xyz.X(), xyz.Y(), xyz.Z() );
+
+ if (( pos = dynamic_cast< const SMDS_FacePosition* >( tgtNode->GetPosition() )))
+ const_cast<SMDS_FacePosition*>( pos )->SetParameters( uvNew.X(), uvNew.Y() );
+
+ addCloseNodes( srcNode, bmTria, srcFaceID, noTriQueue );
+ }
+
+ if ( nbSrcNodes > 0 )
+ {
+ // assure that all src nodes are visited
+ for ( ; iBndSrcN < _bndSrcNodes.size() && noTriQueue.empty(); ++iBndSrcN )
+ {
+ const BRepMesh::ListOfInteger & linkIds = _triaDS->LinksConnectedTo( iBndSrcN );
+ const BRepMesh_PairOfIndex & triaIds = _triaDS->ElementsConnectedTo( linkIds.First() );
+ const BRepMesh_Triangle& tria = _triaDS->GetElement( triaIds.Index(1) );
+ addCloseNodes( _bndSrcNodes[ iBndSrcN ], &tria, srcFaceID, noTriQueue );
+ }
+ if ( noTriQueue.empty() )
+ {
+ SMDS_NodeIteratorPtr nIt = _srcSubMesh->GetSubMeshDS()->GetNodes();
+ while ( nIt->more() )
+ {
+ srcNode = nIt->next();
+ if ( !srcNode->isMarked() )
+ noTriQueue.push_back( make_pair( srcNode, bmTria ));
+ }
+ }
+ }
+ }
+
+ return true;
+
+ } // Morph::Perform
+
+gp_XY Morph::GetBndUV(const int iNode) const
+{
+ return _triaDS->GetNode( iNode ).Coord();
+ }
+
+
+} // namespace StdMeshers_ProjectionUtils
#include "SMESH_StdMeshers.hxx"
+#include "StdMeshers_FaceSide.hxx"
#include "SMDS_MeshElement.hxx"
+#include <BRepMesh_DataStructureOfDelaun.hxx>
+#include <ShapeAnalysis_Surface.hxx>
#include <TopTools_DataMapOfShapeShape.hxx>
-#include <TopTools_IndexedMapOfShape.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Vertex.hxx>
bool Invert();
};
+ /*!
+ * \brief Morph mesh on the target FACE to lie within FACE boundary w/o distortion
+ */
+ class Morph
+ {
+ std::vector< const SMDS_MeshNode* > _bndSrcNodes;
+ Handle(BRepMesh_DataStructureOfDelaun) _triaDS;
+ SMESH_subMesh* _srcSubMesh;
+ bool _moveAll;
+ gp_XY _scale;
+ public:
+
+ Morph(const TSideVector& srcWires);
+
+ bool Perform(SMESH_MesherHelper& tgtHelper,
+ const TSideVector& tgtWires,
+ Handle(ShapeAnalysis_Surface) tgtSurface,
+ const TNodeNodeMap& src2tgtNodes,
+ const bool moveAll);
+
+ // return source boundary nodes. 0-th node is zero
+ const std::vector< const SMDS_MeshNode* >& GetBndNodes() const { return _bndSrcNodes; }
+
+ // return UV of the i-th source boundary node
+ gp_XY GetBndUV(const int iNode) const;
+ };
+
/*!
* \brief Looks for association of all sub-shapes of two shapes
* \param theShape1 - shape 1
return true;
}
- typedef list< pair< const SMDS_MeshNode*, const BRepMesh_Triangle* > > TNodeTriaList;
-
- //================================================================================
- /*!
- * \brief Add in-FACE nodes surrounding a given node to a queue
- */
- //================================================================================
-
- void addCloseNodes( const SMDS_MeshNode* srcNode,
- const BRepMesh_Triangle* bmTria,
- const int srcFaceID,
- TNodeTriaList & noTriQueue )
- {
- // find in-FACE nodes
- SMDS_ElemIteratorPtr elems = srcNode->GetInverseElementIterator(SMDSAbs_Face);
- while ( elems->more() )
- {
- const SMDS_MeshElement* elem = elems->next();
- if ( elem->getshapeId() == srcFaceID )
- {
- for ( int i = 0, nb = elem->NbNodes(); i < nb; ++i )
- {
- const SMDS_MeshNode* n = elem->GetNode( i );
- if ( !n->isMarked() )
- noTriQueue.push_back( make_pair( n, bmTria ));
- }
- }
- }
- }
-
- //================================================================================
- /*!
- * \brief Find a delauney triangle containing a given 2D point and return
- * barycentric coordinates within the found triangle
- */
- //================================================================================
-
- const BRepMesh_Triangle* findTriangle( const gp_XY& uv,
- const BRepMesh_Triangle* bmTria,
- Handle(BRepMesh_DataStructureOfDelaun)& triaDS,
- double bc[3] )
- {
- int nodeIDs[3];
- gp_XY nodeUVs[3];
- int linkIDs[3];
- Standard_Boolean ori[3];
-
- while ( bmTria )
- {
- // check bmTria
-
- triaDS->ElementNodes( *bmTria, nodeIDs );
- nodeUVs[0] = triaDS->GetNode( nodeIDs[0] ).Coord();
- nodeUVs[1] = triaDS->GetNode( nodeIDs[1] ).Coord();
- nodeUVs[2] = triaDS->GetNode( nodeIDs[2] ).Coord();
-
- SMESH_MeshAlgos::GetBarycentricCoords( uv,
- nodeUVs[0], nodeUVs[1], nodeUVs[2],
- bc[0], bc[1] );
- if ( bc[0] >= 0 && bc[1] >= 0 && bc[0] + bc[1] <= 1 )
- {
- bc[2] = 1 - bc[0] - bc[1];
- return bmTria;
- }
-
- // look for a neighbor triangle, which is adjacent to a link intersected
- // by a segment( triangle center -> uv )
-
- gp_XY gc = ( nodeUVs[0] + nodeUVs[1] + nodeUVs[2] ) / 3.;
- gp_XY seg = uv - gc;
-
- bmTria->Edges( linkIDs, ori );
- int triaID = triaDS->IndexOf( *bmTria );
- bmTria = 0;
-
- for ( int i = 0; i < 3; ++i )
- {
- const BRepMesh_PairOfIndex & triIDs = triaDS->ElementsConnectedTo( linkIDs[i] );
- if ( triIDs.Extent() < 2 )
- continue; // no neighbor triangle
-
- // check if a link intersects gc2uv
- const BRepMesh_Edge & link = triaDS->GetLink( linkIDs[i] );
- const BRepMesh_Vertex & n1 = triaDS->GetNode( link.FirstNode() );
- const BRepMesh_Vertex & n2 = triaDS->GetNode( link.LastNode() );
- gp_XY uv1 = n1.Coord();
- gp_XY lin = n2.Coord() - uv1; // link direction
-
- double crossSegLin = seg ^ lin;
- if ( Abs( crossSegLin ) < std::numeric_limits<double>::min() )
- continue; // parallel
-
- double uSeg = ( uv1 - gc ) ^ lin / crossSegLin;
- if ( 0. <= uSeg && uSeg <= 1. )
- {
- bmTria = & triaDS->GetElement( triIDs.Index( 1 + ( triIDs.Index(1) == triaID )));
- break;
- }
- }
- }
- return bmTria;
- }
-
- //================================================================================
- /*!
- * \brief Morph mesh on the target face to lie within FACE boundary w/o distortion
- *
- * algo:
- * - make a CDT on the src FACE
- * - find a triangle containing a src node and get its barycentric coordinates
- * - move the node to a point with the same barycentric coordinates in a corresponding
- * tgt triangle
- */
- //================================================================================
-
- bool morph( SMESH_MesherHelper& tgtHelper,
- const TopoDS_Face& tgtFace,
- const TopoDS_Face& srcFace,
- const TSideVector& tgtWires,
- const TSideVector& srcWires,
- const TAssocTool::TNodeNodeMap& src2tgtNodes )
- {
- if ( srcWires.size() != tgtWires.size() ) return false;
- if ( srcWires.size() == 1 ) return false; // tmp
-
- // count boundary points
- int iP = 1, nbP = 0;
- for ( size_t iW = 0; iW < srcWires.size(); ++iW )
- nbP += srcWires[iW]->NbPoints() - 1; // 1st and last points coincide
-
- // fill boundary points
- BRepMesh::Array1OfVertexOfDelaun srcVert( 1, 1 + nbP ), tgtVert( 1, 1 + nbP );
- vector< const SMDS_MeshNode* > bndSrcNodes( nbP + 1 ); bndSrcNodes[0] = 0;
- BRepMesh_Vertex v( 0, 0, BRepMesh_Frontier );
- for ( size_t iW = 0; iW < srcWires.size(); ++iW )
- {
- const UVPtStructVec& srcPnt = srcWires[iW]->GetUVPtStruct();
- const UVPtStructVec& tgtPnt = tgtWires[iW]->GetUVPtStruct();
- if ( srcPnt.size() != tgtPnt.size() ) return false;
-
- for ( int i = 0, nb = srcPnt.size() - 1; i < nb; ++i, ++iP )
- {
- bndSrcNodes[ iP ] = srcPnt[i].node;
- srcPnt[i].node->setIsMarked( true );
-
- v.ChangeCoord() = srcPnt[i].UV();
- srcVert( iP ) = v;
- v.ChangeCoord() = tgtPnt[i].UV();
- tgtVert( iP ) = v;
- }
- }
- // triangulate the srcFace in 2D
- BRepMesh_Delaun delauney( srcVert );
- Handle(BRepMesh_DataStructureOfDelaun) triaDS = delauney.Result();
-
- Handle(ShapeAnalysis_Surface) tgtSurface = tgtHelper.GetSurface( tgtFace );
- SMESHDS_Mesh* srcMesh = srcWires[0]->GetMesh()->GetMeshDS();
- SMESHDS_Mesh* tgtMesh = tgtHelper.GetMeshDS();
- const SMDS_MeshNode *srcNode, *tgtNode;
- const BRepMesh_Triangle *bmTria;
-
- // un-mark internal src nodes; later we will mark moved nodes
- SMDS_NodeIteratorPtr nIt = srcMesh->MeshElements( srcFace )->GetNodes();
- if ( !nIt || !nIt->more() ) return true;
- while ( nIt->more() )
- ( srcNode = nIt->next() )->setIsMarked( false );
-
- // initialize a queue of nodes with starting triangles
- const int srcFaceID = srcNode->getshapeId();
- TNodeTriaList noTriQueue;
- size_t iBndSrcN = 1;
- for ( ; iBndSrcN < bndSrcNodes.size() && noTriQueue.empty(); ++iBndSrcN )
- {
- // get a triangle
- const BRepMesh::ListOfInteger & linkIds = triaDS->LinksConnectedTo( iBndSrcN );
- const BRepMesh_PairOfIndex & triaIds = triaDS->ElementsConnectedTo( linkIds.First() );
- const BRepMesh_Triangle& tria = triaDS->GetElement( triaIds.Index(1) );
-
- addCloseNodes( bndSrcNodes[ iBndSrcN ], &tria, srcFaceID, noTriQueue );
- }
-
- // Move tgt nodes
-
- double bc[3]; // barycentric coordinates
- int nodeIDs[3];
- bool checkUV = true;
- const SMDS_FacePosition* pos;
-
- while ( !noTriQueue.empty() )
- {
- srcNode = noTriQueue.front().first;
- bmTria = noTriQueue.front().second;
- noTriQueue.pop_front();
- if ( srcNode->isMarked() )
- continue;
- srcNode->setIsMarked( true );
-
- // find a delauney triangle containing the src node
- gp_XY uv = tgtHelper.GetNodeUV( srcFace, srcNode, NULL, &checkUV );
- bmTria = findTriangle( uv, bmTria, triaDS, bc );
- if ( !bmTria )
- continue;
-
- // compute new coordinates for a corresponding tgt node
- gp_XY uvNew( 0., 0. ), nodeUV;
- triaDS->ElementNodes( *bmTria, nodeIDs );
- for ( int i = 0; i < 3; ++i )
- uvNew += bc[i] * tgtVert( nodeIDs[i]).Coord();
- gp_Pnt xyz = tgtSurface->Value( uvNew );
-
- // find and move tgt node
- TAssocTool::TNodeNodeMap::const_iterator n2n = src2tgtNodes.find( srcNode );
- if ( n2n == src2tgtNodes.end() ) continue;
- tgtNode = n2n->second;
- tgtMesh->MoveNode( tgtNode, xyz.X(), xyz.Y(), xyz.Z() );
-
- if (( pos = dynamic_cast< const SMDS_FacePosition* >( tgtNode->GetPosition() )))
- const_cast<SMDS_FacePosition*>( pos )->SetParameters( uvNew.X(), uvNew.Y() );
-
- addCloseNodes( srcNode, bmTria, srcFaceID, noTriQueue );
-
- // assure that all src nodes are visited
- for ( ; iBndSrcN < bndSrcNodes.size() && noTriQueue.empty(); ++iBndSrcN )
- {
- const BRepMesh::ListOfInteger & linkIds = triaDS->LinksConnectedTo( iBndSrcN );
- const BRepMesh_PairOfIndex & triaIds = triaDS->ElementsConnectedTo( linkIds.First() );
- const BRepMesh_Triangle& tria = triaDS->GetElement( triaIds.Index(1) );
- addCloseNodes( bndSrcNodes[ iBndSrcN ], &tria, srcFaceID, noTriQueue );
- }
- }
-
- return true;
- }
-
//=======================================================================
/*
* Set initial association of VERTEXes for the case of projection
// ----------------------------------------------------------------
if ( helper.IsDistorted2D( tgtSubMesh, /*checkUV=*/false, &helper ))
{
- morph( helper, tgtFace, srcFace, tgtWires, srcWires, _src2tgtNodes );
+ TAssocTool::Morph morph( srcWires );
+ morph.Perform( helper, tgtWires, helper.GetSurface( tgtFace ),
+ _src2tgtNodes, /*moveAll=*/true );
if ( !fixDistortedFaces( helper, tgtWires ))
return error("Invalid mesh generated");
#include <string>
#ifdef _DEBUG_
-//#define __myDEBUG
+#define __myDEBUG
//#define __NOT_INVALIDATE_BAD_SMOOTH
//#define __NODES_AT_POS
#endif
enum EFlags { TO_SMOOTH = 0x0000001,
MOVED = 0x0000002, // set by _neibors[i]->SetNewLength()
- SMOOTHED = 0x0000004, // set by this->Smooth()
+ SMOOTHED = 0x0000004, // set by _LayerEdge::Smooth()
DIFFICULT = 0x0000008, // near concave VERTEX
ON_CONCAVE_FACE = 0x0000010,
BLOCKED = 0x0000020, // not to inflate any more
INTERSECTED = 0x0000040, // close intersection with a face found
NORMAL_UPDATED = 0x0000080,
- MARKED = 0x0000100, // local usage
- MULTI_NORMAL = 0x0000200, // a normal is invisible by some of surrounding faces
- NEAR_BOUNDARY = 0x0000400, // is near FACE boundary forcing smooth
- SMOOTHED_C1 = 0x0000800, // is on _eosC1
- DISTORTED = 0x0001000, // was bad before smoothing
- RISKY_SWOL = 0x0002000, // SWOL is parallel to a source FACE
- SHRUNK = 0x0004000, // target node reached a tgt position while shrink()
- UNUSED_FLAG = 0x0100000 // to add use flags after
+ UPD_NORMAL_CONV = 0x0000100, // to update normal on boundary of concave FACE
+ MARKED = 0x0000200, // local usage
+ MULTI_NORMAL = 0x0000400, // a normal is invisible by some of surrounding faces
+ NEAR_BOUNDARY = 0x0000800, // is near FACE boundary forcing smooth
+ SMOOTHED_C1 = 0x0001000, // is on _eosC1
+ DISTORTED = 0x0002000, // was bad before smoothing
+ RISKY_SWOL = 0x0004000, // SWOL is parallel to a source FACE
+ SHRUNK = 0x0008000, // target node reached a tgt position while shrink()
+ UNUSED_FLAG = 0x0100000 // to add user flags after
};
bool Is ( int flag ) const { return _flags & flag; }
void Set ( int flag ) { _flags |= flag; }
const gp_XYZ& PrevPos() const { return _pos[ _pos.size() - 2 ]; }
gp_XYZ PrevCheckPos( _EdgesOnShape* eos=0 ) const;
gp_Ax1 LastSegment(double& segLen, _EdgesOnShape& eos) const;
- gp_XY LastUV( const TopoDS_Face& F, _EdgesOnShape& eos ) const;
+ gp_XY LastUV( const TopoDS_Face& F, _EdgesOnShape& eos, int which=-1 ) const;
bool IsOnEdge() const { return _2neibors; }
gp_XYZ Copy( _LayerEdge& other, _EdgesOnShape& eos, SMESH_MesherHelper& helper );
void SetCosin( double cosin );
_SolidData* _data; // parent SOLID
+ _LayerEdge* operator[](size_t i) const { return (_LayerEdge*) _edges[i]; }
+ size_t size() const { return _edges.size(); }
TopAbs_ShapeEnum ShapeType() const
{ return _shape.IsNull() ? TopAbs_SHAPE : _shape.ShapeType(); }
TopAbs_ShapeEnum SWOLType() const
//--------------------------------------------------------------------------------
/*!
- * \brief Convex FACE whose radius of curvature is less than the thickness of
+ * \brief Convex FACE whose radius of curvature is less than the thickness of
* layers. It is used to detect distortion of prisms based on a convex
* FACE and to update normals to enable further increasing the thickness
*/
// map a sub-shape to _SolidData::_edgesOnShape
map< TGeomID, _EdgesOnShape* > _subIdToEOS;
+ bool _isTooCurved;
bool _normalsFixed;
+ bool _normalsFixedOnBorders; // used in putOnOffsetSurface()
+
+ double GetMaxCurvature( _SolidData& data,
+ _EdgesOnShape& eof,
+ BRepLProp_SLProps& surfProp,
+ SMESH_MesherHelper& helper);
bool GetCenterOfCurvature( _LayerEdge* ledge,
BRepLProp_SLProps& surfProp,
int _nbShapesToSmooth;
- //map< TGeomID,Handle(Geom_Curve)> _edge2curve;
-
vector< _CollisionEdges > _collisionEdges;
set< TGeomID > _concaveFaces;
const gp_XY& uvToFix,
const double refSign );
};
+ struct PyDump;
//--------------------------------------------------------------------------------
/*!
* \brief Builder of viscous layers
void makeOffsetSurface( _EdgesOnShape& eos, SMESH_MesherHelper& );
void putOnOffsetSurface( _EdgesOnShape& eos, int infStep,
vector< _EdgesOnShape* >& eosC1,
- int smooStep=0, bool moveAll=false );
+ int smooStep=0, int moveAll=false );
void findCollisionEdges( _SolidData& data, SMESH_MesherHelper& helper );
+ void findEdgesToUpdateNormalNearConvexFace( _ConvexFace & convFace,
+ _SolidData& data,
+ SMESH_MesherHelper& helper );
void limitMaxLenByCurvature( _SolidData& data, SMESH_MesherHelper& helper );
void limitMaxLenByCurvature( _LayerEdge* e1, _LayerEdge* e2,
_EdgesOnShape& eos1, _EdgesOnShape& eos2,
TopTools_MapOfShape _shrinkedFaces;
int _tmpFaceID;
+ PyDump* _pyDump;
};
//--------------------------------------------------------------------------------
/*!
size_t _iSeg[2]; // index of segment where extreme tgt node is projected
_EdgesOnShape& _eos;
double _curveLen; // length of the EDGE
+ std::pair<int,int> _eToSmooth[2]; // <from,to> indices of _LayerEdge's in _eos
static Handle(Geom_Curve) CurveForSmooth( const TopoDS_Edge& E,
_EdgesOnShape& eos,
bool Perform(_SolidData& data,
Handle(ShapeAnalysis_Surface)& surface,
const TopoDS_Face& F,
- SMESH_MesherHelper& helper )
- {
- if ( _leParams.empty() || ( !isAnalytic() && _offPoints.empty() ))
- prepare( data );
+ SMESH_MesherHelper& helper );
- if ( isAnalytic() )
- return smoothAnalyticEdge( data, surface, F, helper );
- else
- return smoothComplexEdge ( data, surface, F, helper );
- }
void prepare(_SolidData& data );
+ void findEdgesToSmooth();
+
+ bool isToSmooth( int iE );
+
bool smoothAnalyticEdge( _SolidData& data,
Handle(ShapeAnalysis_Surface)& surface,
const TopoDS_Face& F,
SMESH_MesherHelper& helper);
-
bool smoothComplexEdge( _SolidData& data,
Handle(ShapeAnalysis_Surface)& surface,
const TopoDS_Face& F,
SMESH_MesherHelper& helper);
-
gp_XYZ getNormalNormal( const gp_XYZ & normal,
const gp_XYZ& edgeDir);
-
_LayerEdge* getLEdgeOnV( bool is2nd )
{
return _eos._edges[ is2nd ? _eos._edges.size()-1 : 0 ]->_2neibors->_edges[ is2nd ];
// HOWTO use: run python commands written in a console to see
// construction steps of viscous layers
#ifdef __myDEBUG
- ofstream* py;
- int theNbPyFunc;
- struct PyDump {
+ ostream* py;
+ int theNbPyFunc;
+ struct PyDump
+ {
PyDump(SMESH_Mesh& m) {
int tag = 3 + m.GetId();
const char* fname = "/tmp/viscous.py";
cout << "execfile('"<<fname<<"')"<<endl;
- py = new ofstream(fname);
+ py = _pyStream = new ofstream(fname);
*py << "import SMESH" << endl
<< "from salome.smesh import smeshBuilder" << endl
<< "smesh = smeshBuilder.New(salome.myStudy)" << endl
delete py; py=0;
}
~PyDump() { Finish(); cout << "NB FUNCTIONS: " << theNbPyFunc << endl; }
+ struct MyStream : public ostream
+ {
+ template <class T> ostream & operator<<( const T &anything ) { return *this ; }
+ };
+ void Pause() { py = &_mystream; }
+ void Resume() { py = _pyStream; }
+ MyStream _mystream;
+ ostream* _pyStream;
};
#define dumpFunction(f) { _dumpFunction(f, __LINE__);}
#define dumpMove(n) { _dumpMove(n, __LINE__);}
#else
- struct PyDump { PyDump(SMESH_Mesh&) {} void Finish() {} };
+ struct PyDump { PyDump(SMESH_Mesh&) {} void Finish() {} void Pause() {} void Resume() {} };
#define dumpFunction(f) f
#define dumpMove(n)
#define dumpMoveComm(n,txt)
return SMESH_ComputeErrorPtr(); // everything already computed
PyDump debugDump( theMesh );
+ _pyDump = &debugDump;
// TODO: ignore already computed SOLIDs
if ( !findSolidsWithLayers())
{
SMESH_MesherHelper helper( *_mesh );
- const int nbTestPnt = 5; // on a FACE sub-shape
-
BRepLProp_SLProps surfProp( 2, 1e-6 );
data._convexFaces.clear();
continue;
TopoDS_Face F = TopoDS::Face( eof._shape );
- SMESH_subMesh * sm = eof._subMesh;
const TGeomID faceID = eof._shapeID;
BRepAdaptor_Surface surface( F, false );
surfProp.SetSurface( surface );
- bool isTooCurved = false;
-
_ConvexFace cnvFace;
- const double oriFactor = ( F.Orientation() == TopAbs_REVERSED ? +1. : -1. );
- SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true);
- while ( smIt->more() )
- {
- sm = smIt->next();
- const TGeomID subID = sm->GetId();
- // find _LayerEdge's of a sub-shape
- _EdgesOnShape* eos;
- if (( eos = data.GetShapeEdges( subID )))
- cnvFace._subIdToEOS.insert( make_pair( subID, eos ));
- else
- continue;
- // check concavity and curvature and limit data._stepSize
- const double minCurvature =
- 1. / ( eos->_hyp.GetTotalThickness() * ( 1 + theThickToIntersection ));
- size_t iStep = Max( 1, eos->_edges.size() / nbTestPnt );
- for ( size_t i = 0; i < eos->_edges.size(); i += iStep )
- {
- gp_XY uv = helper.GetNodeUV( F, eos->_edges[ i ]->_nodes[0] );
- surfProp.SetParameters( uv.X(), uv.Y() );
- if ( !surfProp.IsCurvatureDefined() )
- continue;
- if ( surfProp.MaxCurvature() * oriFactor > minCurvature )
- {
- limitStepSize( data, 0.9 / surfProp.MaxCurvature() * oriFactor );
- isTooCurved = true;
- }
- if ( surfProp.MinCurvature() * oriFactor > minCurvature )
- {
- limitStepSize( data, 0.9 / surfProp.MinCurvature() * oriFactor );
- isTooCurved = true;
- }
- }
- } // loop on sub-shapes of the FACE
+ cnvFace._face = F;
+ cnvFace._normalsFixed = false;
+ cnvFace._isTooCurved = false;
- if ( !isTooCurved ) continue;
+ double maxCurvature = cnvFace.GetMaxCurvature( data, eof, surfProp, helper );
+ if ( maxCurvature > 0 )
+ {
+ limitStepSize( data, 0.9 / maxCurvature );
+ findEdgesToUpdateNormalNearConvexFace( cnvFace, data, helper );
+ }
+ if ( !cnvFace._isTooCurved ) continue;
_ConvexFace & convFace =
data._convexFaces.insert( make_pair( faceID, cnvFace )).first->second;
- convFace._face = F;
- convFace._normalsFixed = false;
-
// skip a closed surface (data._convexFaces is useful anyway)
bool isClosedF = false;
helper.SetSubShape( F );
if ( isClosedF )
{
// limit _LayerEdge::_maxLen on the FACE
+ const double oriFactor = ( F.Orientation() == TopAbs_REVERSED ? +1. : -1. );
const double minCurvature =
1. / ( eof._hyp.GetTotalThickness() * ( 1 + theThickToIntersection ));
map< TGeomID, _EdgesOnShape* >::iterator id2eos = cnvFace._subIdToEOS.find( faceID );
_LayerEdge* ledge = eos._edges[ i ];
gp_XY uv = helper.GetNodeUV( F, ledge->_nodes[0] );
surfProp.SetParameters( uv.X(), uv.Y() );
- if ( !surfProp.IsCurvatureDefined() )
- continue;
-
- if ( surfProp.MaxCurvature() * oriFactor > minCurvature )
- ledge->_maxLen = Min( ledge->_maxLen, 1. / surfProp.MaxCurvature() * oriFactor );
-
- if ( surfProp.MinCurvature() * oriFactor > minCurvature )
- ledge->_maxLen = Min( ledge->_maxLen, 1. / surfProp.MinCurvature() * oriFactor );
+ if ( surfProp.IsCurvatureDefined() )
+ {
+ double curvature = Max( surfProp.MaxCurvature() * oriFactor,
+ surfProp.MinCurvature() * oriFactor );
+ if ( curvature > minCurvature )
+ ledge->_maxLen = Min( ledge->_maxLen, 1. / curvature );
+ }
}
}
continue;
{
eos._edgeSmoother = new _Smoother1D( curve, eos );
- for ( size_t i = 0; i < eos._edges.size(); ++i )
- eos._edges[i]->Set( _LayerEdge::TO_SMOOTH );
+ // for ( size_t i = 0; i < eos._edges.size(); ++i )
+ // eos._edges[i]->Set( _LayerEdge::TO_SMOOTH );
}
}
}
}
// find _normal
+ bool fromVonF = false;
if ( useGeometry )
{
- bool fromVonF = ( eos.ShapeType() == TopAbs_VERTEX &&
- eos.SWOLType() == TopAbs_FACE &&
- totalNbFaces > 1 );
+ fromVonF = ( eos.ShapeType() == TopAbs_VERTEX &&
+ eos.SWOLType() == TopAbs_FACE &&
+ totalNbFaces > 1 );
if ( onShrinkShape && !fromVonF ) // one of faces the node is on has no layers
{
break;
}
case TopAbs_VERTEX: {
- //if ( eos.SWOLType() != TopAbs_FACE ) // else _cosin is set by getFaceDir()
+ if ( fromVonF )
+ {
+ getFaceDir( TopoDS::Face( eos._sWOL ), TopoDS::Vertex( eos._shape ),
+ node, helper, normOK, &edge._cosin );
+ }
+ else if ( eos.SWOLType() != TopAbs_FACE ) // else _cosin is set by getFaceDir()
{
TopoDS_Vertex V = TopoDS::Vertex( eos._shape );
gp_Vec inFaceDir = getFaceDir( F, V, node, helper, normOK );
double angle = inFaceDir.Angle( edge._normal ); // [0,PI]
edge._cosin = Cos( angle );
if ( totalNbFaces > 2 || helper.IsSeamShape( node->getshapeId() ))
- for ( int iF = totalNbFaces-2; iF >=0; --iF )
+ for ( int iF = 1; iF < totalNbFaces; ++iF )
{
F = face2Norm[ iF ].first;
inFaceDir = getFaceDir( F, V, node, helper, normOK=true );
data._epsilon = data._stepSize * 1e-7;
debugMsg( "-- geomSize = " << data._geomSize << ", stepSize = " << data._stepSize );
+ _pyDump->Pause();
findCollisionEdges( data, helper );
limitMaxLenByCurvature( data, helper );
+ _pyDump->Resume();
+
// limit length of _LayerEdge's around MULTI_NORMAL _LayerEdge's
for ( size_t i = 0; i < data._edgesOnShape.size(); ++i )
if ( data._edgesOnShape[i].ShapeType() == TopAbs_VERTEX &&
// ignore intersection of a _LayerEdge based on a _ConvexFace with a face
// lying on this _ConvexFace
if ( _ConvexFace* convFace = data.GetConvexFace( intFace->getshapeId() ))
- if ( convFace->_subIdToEOS.count ( eos._shapeID ))
+ if ( convFace->_isTooCurved && convFace->_subIdToEOS.count ( eos._shapeID ))
continue;
// ignore intersection of a _LayerEdge based on a FACE with an element on this FACE
if ( dist > 0 )
{
bool toIgnore = false;
- if ( eos._edges[i]->Is( _LayerEdge::TO_SMOOTH ))
+ if ( eos._toSmooth )
{
const TopoDS_Shape& S = getMeshDS()->IndexToShape( intFace->getshapeId() );
if ( !S.IsNull() && S.ShapeType() == TopAbs_FACE )
{
- TopExp_Explorer edge( eos._shape, TopAbs_EDGE );
- for ( ; !toIgnore && edge.More(); edge.Next() )
- // is adjacent - has a common EDGE
- toIgnore = ( helper.IsSubShape( edge.Current(), S ));
+ TopExp_Explorer sub( eos._shape,
+ eos.ShapeType() == TopAbs_FACE ? TopAbs_EDGE : TopAbs_VERTEX );
+ for ( ; !toIgnore && sub.More(); sub.Next() )
+ // is adjacent - has a common EDGE or VERTEX
+ toIgnore = ( helper.IsSubShape( sub.Current(), S ));
if ( toIgnore ) // check angle between normals
{
int infStep,
vector< _EdgesOnShape* >& eosC1,
int smooStep,
- bool moveAll )
+ int moveAll )
{
_EdgesOnShape * eof = & eos;
if ( eos.ShapeType() != TopAbs_FACE ) // eos is a boundary of C1 FACE, look for the FACE eos
edge->Unset( _LayerEdge::MARKED );
if ( edge->Is( _LayerEdge::BLOCKED ) || !edge->_curvature )
continue;
- if ( !moveAll && !edge->Is( _LayerEdge::MOVED ))
+ if ( moveAll == _LayerEdge::UPD_NORMAL_CONV )
+ {
+ if ( !edge->Is( _LayerEdge::UPD_NORMAL_CONV ))
continue;
+ }
+ else if ( !moveAll && !edge->Is( _LayerEdge::MOVED ))
+ continue;
int nbBlockedAround = 0;
for ( size_t iN = 0; iN < edge->_neibors.size(); ++iN )
gp_Pnt tgtP = SMESH_TNodeXYZ( edge->_nodes.back() );
gp_Pnt2d uv = eof->_offsetSurf->NextValueOfUV( edge->_curvature->_uv, tgtP, preci );
- if ( eof->_offsetSurf->Gap() > edge->_len ) continue; // NextValueOfUV() bug
+ if ( eof->_offsetSurf->Gap() > edge->_len ) continue; // NextValueOfUV() bug
edge->_curvature->_uv = uv;
if ( eof->_offsetSurf->Gap() < 10 * preci ) continue; // same pos
edge->_pos.back() = newP;
edge->Set( _LayerEdge::MARKED );
+ if ( moveAll == _LayerEdge::UPD_NORMAL_CONV )
+ {
+ edge->_normal = ( newP - prevP ).Normalized();
+ }
}
}
+
+
#ifdef _DEBUG_
// dumpMove() for debug
size_t i = 0;
break;
if ( i < eos._edges.size() )
{
- dumpFunction(SMESH_Comment("putOnOffsetSurface_F") << eos._shapeID
+ dumpFunction(SMESH_Comment("putOnOffsetSurface_S") << eos._shapeID
<< "_InfStep" << infStep << "_" << smooStep );
for ( ; i < eos._edges.size(); ++i )
{
dumpFunctionEnd();
}
#endif
+
+ _ConvexFace* cnvFace;
+ if ( moveAll != _LayerEdge::UPD_NORMAL_CONV &&
+ eos.ShapeType() == TopAbs_FACE &&
+ (cnvFace = eos.GetData().GetConvexFace( eos._shapeID )) &&
+ !cnvFace->_normalsFixedOnBorders )
+ {
+ // put on the surface nodes built on FACE boundaries
+ SMESH_subMeshIteratorPtr smIt = eos._subMesh->getDependsOnIterator(/*includeSelf=*/false);
+ while ( smIt->more() )
+ {
+ SMESH_subMesh* sm = smIt->next();
+ _EdgesOnShape* subEOS = eos.GetData().GetShapeEdges( sm->GetId() );
+ if ( !subEOS->_sWOL.IsNull() ) continue;
+ if ( std::find( eosC1.begin(), eosC1.end(), subEOS ) != eosC1.end() ) continue;
+
+ putOnOffsetSurface( *subEOS, infStep, eosC1, smooStep, _LayerEdge::UPD_NORMAL_CONV );
+ }
+ cnvFace->_normalsFixedOnBorders = true;
+ }
}
//================================================================================
return Handle(Geom_Curve)();
}
+//================================================================================
+/*!
+ * \brief Smooth edges on EDGE
+ */
+//================================================================================
+
+bool _Smoother1D::Perform(_SolidData& data,
+ Handle(ShapeAnalysis_Surface)& surface,
+ const TopoDS_Face& F,
+ SMESH_MesherHelper& helper )
+{
+ if ( _leParams.empty() || ( !isAnalytic() && _offPoints.empty() ))
+ prepare( data );
+
+ findEdgesToSmooth();
+ if ( isAnalytic() )
+ return smoothAnalyticEdge( data, surface, F, helper );
+ else
+ return smoothComplexEdge ( data, surface, F, helper );
+}
+
+//================================================================================
+/*!
+ * \brief Find edges to smooth
+ */
+//================================================================================
+
+void _Smoother1D::findEdgesToSmooth()
+{
+ _LayerEdge* leOnV[2] = { getLEdgeOnV(0), getLEdgeOnV(1) };
+ for ( int iEnd = 0; iEnd < 2; ++iEnd )
+ if ( leOnV[iEnd]->Is( _LayerEdge::NORMAL_UPDATED ))
+ _leOnV[iEnd]._cosin = Abs( _edgeDir[iEnd].Normalized() * leOnV[iEnd]->_normal );
+
+ _eToSmooth[0].first = _eToSmooth[0].second = 0;
+
+ for ( size_t i = 0; i < _eos.size(); ++i )
+ {
+ if ( !_eos[i]->Is( _LayerEdge::TO_SMOOTH ))
+ {
+ if ( needSmoothing( _leOnV[0]._cosin, _eos[i]->_len, _curveLen * _leParams[i] ) ||
+ isToSmooth( i ))
+ _eos[i]->Set( _LayerEdge::TO_SMOOTH );
+ else
+ break;
+ }
+ _eToSmooth[0].second = i+1;
+ }
+
+ _eToSmooth[1].first = _eToSmooth[1].second = _eos.size();
+
+ for ( int i = _eos.size() - 1; i >= _eToSmooth[0].second; --i )
+ {
+ if ( !_eos[i]->Is( _LayerEdge::TO_SMOOTH ))
+ {
+ if ( needSmoothing( _leOnV[1]._cosin, _eos[i]->_len, _curveLen * ( 1.-_leParams[i] )) ||
+ isToSmooth( i ))
+ _eos[i]->Set( _LayerEdge::TO_SMOOTH );
+ else
+ break;
+ }
+ _eToSmooth[1].first = i;
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Check if iE-th _LayerEdge needs smoothing
+ */
+//================================================================================
+
+bool _Smoother1D::isToSmooth( int iE )
+{
+ SMESH_NodeXYZ pi( _eos[iE]->_nodes[0] );
+ SMESH_NodeXYZ p0( _eos[iE]->_2neibors->srcNode(0) );
+ SMESH_NodeXYZ p1( _eos[iE]->_2neibors->srcNode(1) );
+ gp_XYZ seg0 = pi - p0;
+ gp_XYZ seg1 = p1 - pi;
+ gp_XYZ tangent = seg0 + seg1;
+ double tangentLen = tangent.Modulus();
+ double segMinLen = Min( seg0.Modulus(), seg1.Modulus() );
+ if ( tangentLen < std::numeric_limits<double>::min() )
+ return false;
+ tangent /= tangentLen;
+
+ for ( size_t i = 0; i < _eos[iE]->_neibors.size(); ++i )
+ {
+ _LayerEdge* ne = _eos[iE]->_neibors[i];
+ if ( !ne->Is( _LayerEdge::TO_SMOOTH ) ||
+ ne->_nodes.size() < 2 ||
+ ne->_nodes[0]->GetPosition()->GetDim() != 2 )
+ continue;
+ gp_XYZ edgeVec = SMESH_NodeXYZ( ne->_nodes.back() ) - SMESH_NodeXYZ( ne->_nodes[0] );
+ double proj = edgeVec * tangent;
+ if ( needSmoothing( 1., proj, segMinLen ))
+ return true;
+ }
+ return false;
+}
+
//================================================================================
/*!
* \brief smooth _LayerEdge's on a staight EDGE or circular EDGE
{
if ( !isAnalytic() ) return false;
- const size_t iFrom = 0, iTo = _eos._edges.size();
+ size_t iFrom = 0, iTo = _eos._edges.size();
if ( _anaCurve->IsKind( STANDARD_TYPE( Geom_Line )))
{
if ( F.IsNull() ) // 3D
{
- SMESH_TNodeXYZ p0 ( _eos._edges[iFrom]->_2neibors->tgtNode(0) );
- SMESH_TNodeXYZ p1 ( _eos._edges[iTo-1]->_2neibors->tgtNode(1) );
SMESH_TNodeXYZ pSrc0( _eos._edges[iFrom]->_2neibors->srcNode(0) );
SMESH_TNodeXYZ pSrc1( _eos._edges[iTo-1]->_2neibors->srcNode(1) );
- gp_XYZ newPos, lineDir = pSrc1 - pSrc0;
- _LayerEdge* vLE0 = _eos._edges[iFrom]->_2neibors->_edges[0];
- _LayerEdge* vLE1 = _eos._edges[iTo-1]->_2neibors->_edges[1];
- bool shiftOnly = ( vLE0->Is( _LayerEdge::NORMAL_UPDATED ) ||
- vLE0->Is( _LayerEdge::BLOCKED ) ||
- vLE1->Is( _LayerEdge::NORMAL_UPDATED ) ||
- vLE1->Is( _LayerEdge::BLOCKED ));
- for ( size_t i = iFrom; i < iTo; ++i )
- {
- _LayerEdge* edge = _eos._edges[i];
- SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( edge->_nodes.back() );
- newPos = p0 * ( 1. - _leParams[i] ) + p1 * _leParams[i];
-
- if ( shiftOnly || edge->Is( _LayerEdge::NORMAL_UPDATED ))
- {
- gp_XYZ curPos = SMESH_TNodeXYZ ( tgtNode );
- double shift = ( lineDir * ( newPos - pSrc0 ) -
- lineDir * ( curPos - pSrc0 ));
- newPos = curPos + lineDir * shift / lineDir.SquareModulus();
- }
- if ( edge->Is( _LayerEdge::BLOCKED ))
+ //const gp_XYZ lineDir = pSrc1 - pSrc0;
+ //_LayerEdge* vLE0 = getLEdgeOnV( 0 );
+ //_LayerEdge* vLE1 = getLEdgeOnV( 1 );
+ // bool shiftOnly = ( vLE0->Is( _LayerEdge::NORMAL_UPDATED ) ||
+ // vLE0->Is( _LayerEdge::BLOCKED ) ||
+ // vLE1->Is( _LayerEdge::NORMAL_UPDATED ) ||
+ // vLE1->Is( _LayerEdge::BLOCKED ));
+ for ( int iEnd = 0; iEnd < 2; ++iEnd )
+ {
+ iFrom = _eToSmooth[ iEnd ].first, iTo = _eToSmooth[ iEnd ].second;
+ if ( iFrom >= iTo ) continue;
+ SMESH_TNodeXYZ p0( _eos[iFrom]->_2neibors->tgtNode(0) );
+ SMESH_TNodeXYZ p1( _eos[iTo-1]->_2neibors->tgtNode(1) );
+ double param0 = ( iFrom == 0 ) ? 0. : _leParams[ iFrom-1 ];
+ double param1 = _leParams[ iTo ];
+ for ( size_t i = iFrom; i < iTo; ++i )
{
- SMESH_TNodeXYZ pSrc( edge->_nodes[0] );
- double curThick = pSrc.SquareDistance( tgtNode );
- double newThink = ( pSrc - newPos ).SquareModulus();
- if ( newThink > curThick )
- continue;
+ _LayerEdge* edge = _eos[i];
+ SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( edge->_nodes.back() );
+ double param = ( _leParams[i] - param0 ) / ( param1 - param0 );
+ gp_XYZ newPos = p0 * ( 1. - param ) + p1 * param;
+
+ // if ( shiftOnly || edge->Is( _LayerEdge::NORMAL_UPDATED ))
+ // {
+ // gp_XYZ curPos = SMESH_TNodeXYZ ( tgtNode );
+ // double shift = ( lineDir * ( newPos - pSrc0 ) -
+ // lineDir * ( curPos - pSrc0 ));
+ // newPos = curPos + lineDir * shift / lineDir.SquareModulus();
+ // }
+ if ( edge->Is( _LayerEdge::BLOCKED ))
+ {
+ SMESH_TNodeXYZ pSrc( edge->_nodes[0] );
+ double curThick = pSrc.SquareDistance( tgtNode );
+ double newThink = ( pSrc - newPos ).SquareModulus();
+ if ( newThink > curThick )
+ continue;
+ }
+ edge->_pos.back() = newPos;
+ tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
+ dumpMove( tgtNode );
}
- edge->_pos.back() = newPos;
- tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
- dumpMove( tgtNode );
}
}
else // 2D
{
- _LayerEdge* e0 = getLEdgeOnV( 0 );
- _LayerEdge* e1 = getLEdgeOnV( 1 );
- gp_XY uv0 = e0->LastUV( F, *data.GetShapeEdges( e0 ));
- gp_XY uv1 = e1->LastUV( F, *data.GetShapeEdges( e1 ));
- if ( e0->_nodes.back() == e1->_nodes.back() ) // closed edge
+ _LayerEdge* eV0 = getLEdgeOnV( 0 );
+ _LayerEdge* eV1 = getLEdgeOnV( 1 );
+ gp_XY uvV0 = eV0->LastUV( F, *data.GetShapeEdges( eV0 ));
+ gp_XY uvV1 = eV1->LastUV( F, *data.GetShapeEdges( eV1 ));
+ if ( eV0->_nodes.back() == eV1->_nodes.back() ) // closed edge
{
int iPeriodic = helper.GetPeriodicIndex();
if ( iPeriodic == 1 || iPeriodic == 2 )
{
- uv1.SetCoord( iPeriodic, helper.GetOtherParam( uv1.Coord( iPeriodic )));
- if ( uv0.Coord( iPeriodic ) > uv1.Coord( iPeriodic ))
- std::swap( uv0, uv1 );
+ uvV1.SetCoord( iPeriodic, helper.GetOtherParam( uvV1.Coord( iPeriodic )));
+ if ( uvV0.Coord( iPeriodic ) > uvV1.Coord( iPeriodic ))
+ std::swap( uvV0, uvV1 );
}
}
- const gp_XY rangeUV = uv1 - uv0;
- for ( size_t i = iFrom; i < iTo; ++i )
- {
- if ( _eos._edges[i]->Is( _LayerEdge::BLOCKED )) continue;
- gp_XY newUV = uv0 + _leParams[i] * rangeUV;
- _eos._edges[i]->_pos.back().SetCoord( newUV.X(), newUV.Y(), 0 );
-
- gp_Pnt newPos = surface->Value( newUV.X(), newUV.Y() );
- SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( _eos._edges[i]->_nodes.back() );
- tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
- dumpMove( tgtNode );
+ for ( int iEnd = 0; iEnd < 2; ++iEnd )
+ {
+ iFrom = _eToSmooth[ iEnd ].first, iTo = _eToSmooth[ iEnd ].second;
+ if ( iFrom >= iTo ) continue;
+ _LayerEdge* e0 = _eos[iFrom]->_2neibors->_edges[0];
+ _LayerEdge* e1 = _eos[iTo-1]->_2neibors->_edges[1];
+ gp_XY uv0 = ( e0 == eV0 ) ? uvV0 : e0->LastUV( F, _eos );
+ gp_XY uv1 = ( e1 == eV1 ) ? uvV1 : e1->LastUV( F, _eos );
+ double param0 = ( iFrom == 0 ) ? 0. : _leParams[ iFrom-1 ];
+ double param1 = _leParams[ iTo ];
+ const gp_XY rangeUV = uv1 - uv0;
+ for ( size_t i = iFrom; i < iTo; ++i )
+ {
+ if ( _eos[i]->Is( _LayerEdge::BLOCKED )) continue;
+ double param = ( _leParams[i] - param0 ) / ( param1 - param0 );
+ gp_XY newUV = uv0 + param * rangeUV;
+ _eos[i]->_pos.back().SetCoord( newUV.X(), newUV.Y(), 0 );
+
+ gp_Pnt newPos = surface->Value( newUV.X(), newUV.Y() );
+ SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( _eos[i]->_nodes.back() );
+ tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
+ dumpMove( tgtNode );
- SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
- pos->SetUParameter( newUV.X() );
- pos->SetVParameter( newUV.Y() );
+ SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
+ pos->SetUParameter( newUV.X() );
+ pos->SetVParameter( newUV.Y() );
+ }
}
}
return true;
if ( uLast < 0 )
uLast += 2 * M_PI;
- for ( size_t i = iFrom; i < iTo; ++i )
+ for ( size_t i = 0; i < _eos.size(); ++i )
{
- if ( _eos._edges[i]->Is( _LayerEdge::BLOCKED )) continue;
+ if ( _eos[i]->Is( _LayerEdge::BLOCKED )) continue;
+ //if ( !_eos[i]->Is( _LayerEdge::TO_SMOOTH )) continue;
double u = uLast * _leParams[i];
gp_Pnt p = ElCLib::Value( u, newCirc );
_eos._edges[i]->_pos.back() = p.XYZ();
gp_Ax2d axis( center, vec0 );
gp_Circ2d circ( axis, radius );
- for ( size_t i = iFrom; i < iTo; ++i )
+ for ( size_t i = 0; i < _eos.size(); ++i )
{
- if ( _eos._edges[i]->Is( _LayerEdge::BLOCKED )) continue;
+ if ( _eos[i]->Is( _LayerEdge::BLOCKED )) continue;
+ //if ( !_eos[i]->Is( _LayerEdge::TO_SMOOTH )) continue;
double newU = uLast * _leParams[i];
gp_Pnt2d newUV = ElCLib::Value( newU, circ );
_eos._edges[i]->_pos.back().SetCoord( newUV.X(), newUV.Y(), 0 );
if ( _offPoints.empty() )
return false;
+ // ----------------------------------------------
// move _offPoints along normals of _LayerEdge's
+ // ----------------------------------------------
_LayerEdge* e[2] = { getLEdgeOnV(0), getLEdgeOnV(1) };
if ( e[0]->Is( _LayerEdge::NORMAL_UPDATED ))
}
}
+ // -----------------------------------------------------------------
// project tgt nodes of extreme _LayerEdge's to the offset segments
+ // -----------------------------------------------------------------
if ( e[0]->Is( _LayerEdge::NORMAL_UPDATED )) _iSeg[0] = 0;
if ( e[1]->Is( _LayerEdge::NORMAL_UPDATED )) _iSeg[1] = _offPoints.size()-2;
if ( e[1]->_normal * vDiv1.XYZ() < 0 ) e[1]->_len += d1;
else e[1]->_len -= d1;
+ // ---------------------------------------------------------------------------------
// compute normalized length of the offset segments located between the projections
+ // ---------------------------------------------------------------------------------
size_t iSeg = 0, nbSeg = _iSeg[1] - _iSeg[0] + 1;
vector< double > len( nbSeg + 1 );
_offPoints[ _iSeg[0] ]._xyz = pExtreme[0].XYZ();
_offPoints[ _iSeg[1]+ 1]._xyz = pExtreme[1].XYZ();
+ // -------------------------------------------------------------
// distribute tgt nodes of _LayerEdge's between the projections
+ // -------------------------------------------------------------
iSeg = 0;
- for ( size_t i = 0; i < _eos._edges.size(); ++i )
+ for ( size_t i = 0; i < _eos.size(); ++i )
{
- if ( _eos._edges[i]->Is( _LayerEdge::BLOCKED )) continue;
+ if ( _eos[i]->Is( _LayerEdge::BLOCKED )) continue;
+ //if ( !_eos[i]->Is( _LayerEdge::TO_SMOOTH )) continue;
while ( iSeg+2 < len.size() && _leParams[i] > len[ iSeg+1 ] )
iSeg++;
double r = ( _leParams[i] - len[ iSeg ]) / ( len[ iSeg+1 ] - len[ iSeg ]);
if ( surface.IsNull() )
{
- _eos._edges[i]->_pos.back() = p;
+ _eos[i]->_pos.back() = p;
}
else // project a new node position to a FACE
{
- gp_Pnt2d uv ( _eos._edges[i]->_pos.back().X(), _eos._edges[i]->_pos.back().Y() );
+ gp_Pnt2d uv ( _eos[i]->_pos.back().X(), _eos[i]->_pos.back().Y() );
gp_Pnt2d uv2( surface->NextValueOfUV( uv, p, fTol ));
p = surface->Value( uv2 ).XYZ();
- _eos._edges[i]->_pos.back().SetCoord( uv2.X(), uv2.Y(), 0 );
+ _eos[i]->_pos.back().SetCoord( uv2.X(), uv2.Y(), 0 );
}
- SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( _eos._edges[i]->_nodes.back() );
+ SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( _eos[i]->_nodes.back() );
tgtNode->setXYZ( p.X(), p.Y(), p.Z() );
dumpMove( tgtNode );
}
double fullLen = _leParams.back() + pPrev.Distance( SMESH_TNodeXYZ( getLEdgeOnV(1)->_nodes[0]));
for ( size_t i = 0; i < _leParams.size()-1; ++i )
_leParams[i] = _leParams[i+1] / fullLen;
+ _leParams.back() = 1.;
}
+ _LayerEdge* leOnV[2] = { getLEdgeOnV(0), getLEdgeOnV(1) };
+
+ // get cosin to use in findEdgesToSmooth()
+ _edgeDir[0] = getEdgeDir( E, leOnV[0]->_nodes[0], data.GetHelper() );
+ _edgeDir[1] = getEdgeDir( E, leOnV[1]->_nodes[0], data.GetHelper() );
+ _leOnV[0]._cosin = Abs( leOnV[0]->_cosin );
+ _leOnV[1]._cosin = Abs( leOnV[1]->_cosin );
+ if ( _eos._sWOL.IsNull() ) // 3D
+ for ( int iEnd = 0; iEnd < 2; ++iEnd )
+ _leOnV[iEnd]._cosin = Abs( _edgeDir[iEnd].Normalized() * leOnV[iEnd]->_normal );
+
if ( isAnalytic() )
return;
_offPoints[i]._param = GCPnts_AbscissaPoint::Length( c3dAdaptor, u0, u ) / _curveLen;
}
- _LayerEdge* leOnV[2] = { getLEdgeOnV(0), getLEdgeOnV(1) };
-
// set _2edges
_offPoints [0]._2edges.set( &_leOnV[0], &_leOnV[0], 0.5, 0.5 );
_offPoints.back()._2edges.set( &_leOnV[1], &_leOnV[1], 0.5, 0.5 );
int iLBO = _offPoints.size() - 2; // last but one
- _edgeDir[0] = getEdgeDir( E, leOnV[0]->_nodes[0], data.GetHelper() );
- _edgeDir[1] = getEdgeDir( E, leOnV[1]->_nodes[0], data.GetHelper() );
-
_leOnV[ 0 ]._normal = getNormalNormal( leOnV[0]->_normal, _edgeDir[0] );
_leOnV[ 1 ]._normal = getNormalNormal( leOnV[1]->_normal, _edgeDir[1] );
_leOnV[ 0 ]._len = 0;
}
}
+//================================================================================
+/*!
+ * \brief Find _LayerEdge's located on boundary of a convex FACE whose normal
+ * will be updated at each inflation step
+ */
+//================================================================================
+
+void _ViscousBuilder::findEdgesToUpdateNormalNearConvexFace( _ConvexFace & convFace,
+ _SolidData& data,
+ SMESH_MesherHelper& helper )
+{
+ const TGeomID convFaceID = getMeshDS()->ShapeToIndex( convFace._face );
+ const double preci = BRep_Tool::Tolerance( convFace._face );
+ Handle(ShapeAnalysis_Surface) surface = helper.GetSurface( convFace._face );
+
+ bool edgesToUpdateFound = false;
+
+ map< TGeomID, _EdgesOnShape* >::iterator id2eos = convFace._subIdToEOS.begin();
+ for ( ; id2eos != convFace._subIdToEOS.end(); ++id2eos )
+ {
+ _EdgesOnShape& eos = * id2eos->second;
+ if ( !eos._sWOL.IsNull() ) continue;
+ if ( !eos._hyp.ToSmooth() ) continue;
+ for ( size_t i = 0; i < eos._edges.size(); ++i )
+ {
+ _LayerEdge* ledge = eos._edges[ i ];
+ if ( ledge->Is( _LayerEdge::UPD_NORMAL_CONV )) continue; // already checked
+ if ( ledge->Is( _LayerEdge::MULTI_NORMAL )) continue; // not inflatable
+
+ gp_XYZ tgtPos = ( SMESH_NodeXYZ( ledge->_nodes[0] ) +
+ ledge->_normal * ledge->_lenFactor * ledge->_maxLen );
+
+ // the normal must be updated if distance from tgtPos to surface is less than
+ // target thickness
+
+ // find an initial UV for search of a projection of tgtPos to surface
+ const SMDS_MeshNode* nodeInFace = 0;
+ SMDS_ElemIteratorPtr fIt = ledge->_nodes[0]->GetInverseElementIterator(SMDSAbs_Face);
+ while ( fIt->more() && !nodeInFace )
+ {
+ const SMDS_MeshElement* f = fIt->next();
+ if ( convFaceID != f->getshapeId() ) continue;
+
+ SMDS_ElemIteratorPtr nIt = f->nodesIterator();
+ while ( nIt->more() && !nodeInFace )
+ {
+ const SMDS_MeshElement* n = nIt->next();
+ if ( n->getshapeId() == convFaceID )
+ nodeInFace = static_cast< const SMDS_MeshNode* >( n );
+ }
+ }
+ if ( !nodeInFace )
+ continue;
+ gp_XY uv = helper.GetNodeUV( convFace._face, nodeInFace );
+
+ // projection
+ surface->NextValueOfUV( uv, tgtPos, preci );
+ double dist = surface->Gap();
+ if ( dist < 0.95 * ledge->_maxLen )
+ {
+ ledge->Set( _LayerEdge::UPD_NORMAL_CONV );
+ if ( !ledge->_curvature ) ledge->_curvature = new _Curvature;
+ ledge->_curvature->_uv.SetCoord( uv.X(), uv.Y() );
+ edgesToUpdateFound = true;
+ }
+ }
+ }
+
+ if ( !convFace._isTooCurved && edgesToUpdateFound )
+ {
+ data._convexFaces.insert( make_pair( convFaceID, convFace )).first->second;
+ }
+}
+
//================================================================================
/*!
* \brief Modify normals of _LayerEdge's on EDGE's to avoid intersection with
for ( ; id2face != data._convexFaces.end(); ++id2face )
{
_ConvexFace & convFace = (*id2face).second;
+ convFace._normalsFixedOnBorders = false; // to update at each inflation step
+
if ( convFace._normalsFixed )
continue; // already fixed
if ( convFace.CheckPrisms() )
return true;
}
+//================================================================================
+/*!
+ * \brief Return max curvature of a FACE
+ */
+//================================================================================
+
+double _ConvexFace::GetMaxCurvature( _SolidData& data,
+ _EdgesOnShape& eof,
+ BRepLProp_SLProps& surfProp,
+ SMESH_MesherHelper& helper)
+{
+ double maxCurvature = 0;
+
+ TopoDS_Face F = TopoDS::Face( eof._shape );
+
+ const int nbTestPnt = 5;
+ const double oriFactor = ( F.Orientation() == TopAbs_REVERSED ? +1. : -1. );
+ SMESH_subMeshIteratorPtr smIt = eof._subMesh->getDependsOnIterator(/*includeSelf=*/true);
+ while ( smIt->more() )
+ {
+ SMESH_subMesh* sm = smIt->next();
+ const TGeomID subID = sm->GetId();
+
+ // find _LayerEdge's of a sub-shape
+ _EdgesOnShape* eos;
+ if (( eos = data.GetShapeEdges( subID )))
+ this->_subIdToEOS.insert( make_pair( subID, eos ));
+ else
+ continue;
+
+ // check concavity and curvature and limit data._stepSize
+ const double minCurvature =
+ 1. / ( eos->_hyp.GetTotalThickness() * ( 1 + theThickToIntersection ));
+ size_t iStep = Max( 1, eos->_edges.size() / nbTestPnt );
+ for ( size_t i = 0; i < eos->_edges.size(); i += iStep )
+ {
+ gp_XY uv = helper.GetNodeUV( F, eos->_edges[ i ]->_nodes[0] );
+ surfProp.SetParameters( uv.X(), uv.Y() );
+ if ( surfProp.IsCurvatureDefined() )
+ {
+ double curvature = Max( surfProp.MaxCurvature() * oriFactor,
+ surfProp.MinCurvature() * oriFactor );
+ maxCurvature = Max( maxCurvature, curvature );
+
+ if ( curvature > minCurvature )
+ this->_isTooCurved = true;
+ }
+ }
+ } // loop on sub-shapes of the FACE
+
+ return maxCurvature;
+}
+
//================================================================================
/*!
* \brief Finds a center of curvature of a surface at a _LayerEdge
//================================================================================
/*!
- * \brief Return the last position of the target node on a FACE.
+ * \brief Return the last (or \a which) position of the target node on a FACE.
* \param [in] F - the FACE this _LayerEdge is inflated along
+ * \param [in] which - index of position
* \return gp_XY - result UV
*/
//================================================================================
-gp_XY _LayerEdge::LastUV( const TopoDS_Face& F, _EdgesOnShape& eos ) const
+gp_XY _LayerEdge::LastUV( const TopoDS_Face& F, _EdgesOnShape& eos, int which ) const
{
if ( F.IsSame( eos._sWOL )) // F is my FACE
return gp_XY( _pos.back().X(), _pos.back().Y() );
return gp_XY( 1e100, 1e100 );
// _sWOL is EDGE of F; _pos.back().X() is the last U on the EDGE
- double f, l, u = _pos.back().X();
+ double f, l, u = _pos[ which < 0 ? _pos.size()-1 : which ].X();
Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface( TopoDS::Edge(eos._sWOL), F, f,l);
if ( !C2d.IsNull() && f <= u && u <= l )
return C2d->Value( u ).XY();
* \param [in] eov - EOS of the VERTEX
* \param [in] eos - EOS of the FACE
* \param [in] step - inflation step
- * \param [in,out] badSmooEdges - not untangled _LayerEdge's
+ * \param [in,out] badSmooEdges - tangled _LayerEdge's
*/
//================================================================================
//if ( Is( BLOCKED )) return;
Set( BLOCKED );
+ SMESH_Comment msg( "#BLOCK shape=");
+ msg << data.GetShapeEdges( this )->_shapeID
+ << ", nodes " << _nodes[0]->GetID() << ", " << _nodes.back()->GetID();
+ dumpCmd( msg + " -- BEGIN")
+
_maxLen = _len;
std::queue<_LayerEdge*> queue;
queue.push( this );
//if ( edge->_nodes[0]->getshapeId() == neibor->_nodes[0]->getshapeId() ) viscous_layers_00/A3
{
newMaxLen *= edge->_lenFactor / neibor->_lenFactor;
+ // newMaxLen *= Min( edge->_lenFactor / neibor->_lenFactor,
+ // neibor->_lenFactor / edge->_lenFactor );
}
if ( neibor->_maxLen > newMaxLen )
{
}
}
}
+ dumpCmd( msg + " -- END")
}
//================================================================================
case BLOCKED: dump << "BLOCKED"; break;
case INTERSECTED: dump << "INTERSECTED"; break;
case NORMAL_UPDATED: dump << "NORMAL_UPDATED"; break;
+ case UPD_NORMAL_CONV: dump << "UPD_NORMAL_CONV"; break;
case MARKED: dump << "MARKED"; break;
case MULTI_NORMAL: dump << "MULTI_NORMAL"; break;
case NEAR_BOUNDARY: dump << "NEAR_BOUNDARY"; break;
double f,l, u = 0;
gp_XY uv;
vector< gp_XYZ > pos3D;
- bool isOnEdge;
+ bool isOnEdge, isTooConvexFace = false;
TGeomID prevBaseId = -1;
TNode2Edge* n2eMap = 0;
TNode2Edge::iterator n2e;
for ( size_t j = 0; j < eos._eosC1[i]->_edges.size(); ++j )
eos._eosC1[i]->_edges[j]->Set( _LayerEdge::SMOOTHED_C1 );
}
+ isTooConvexFace = false;
+ if ( _ConvexFace* cf = data.GetConvexFace( eos._shapeID ))
+ isTooConvexFace = cf->_isTooCurved;
}
vector< double > segLen;
if ( eos._sWOL.IsNull() )
{
bool useNormal = true;
- bool usePos = false;
- bool smoothed = false;
+ bool usePos = false;
+ bool smoothed = false;
double preci = 0.1 * edge._len;
if ( eos._toSmooth && edge._pos.size() > 2 )
{
}
if ( smoothed )
{
- if ( !surface.IsNull() &&
- !data._convexFaces.count( eos._shapeID )) // edge smoothed on FACE
+ if ( !surface.IsNull() && !isTooConvexFace ) // edge smoothed on FACE
{
useNormal = usePos = false;
gp_Pnt2d uv = helper.GetNodeUV( geomFace, edge._nodes[0] );