We have added a new feature to the 3D Model Editor. It can reconstruct the cells with bad cell normals, and the updated cell normals now face outwards. This aligns with the principles of light reflection.

Tool: https://www.weiy.city/functions/3D-Model-Editor/

Demo video:

The red area indicates the cells with bad cell normals. After clicking on the button flip cell normal, the original mesh will be modified. The order of points in these cells will be inversed. Then you can download the new 3D model.

If you want to use the function, your uploaded model file needs to be a convex polyhedron and cannot have non-manifold edges and points.

The code for create the test data in the above video:

#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkTransform.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkAxesActor.h>
#include <vtkLine.h>
#include <vtkPlane.h>
#include <vtkSTLWriter.h>

#include "point.hpp"

using namespace std;

#define vtkSPtr vtkSmartPointer
#define vtkSPtrNew(Var, Type) vtkSPtr<Type> Var = vtkSPtr<Type>::New();

int main()
{
    vtkSPtrNew( points, vtkPoints );
    points->InsertNextPoint( -1, 0, 1 );
    points->InsertNextPoint( 1, 0, 1 );
    points->InsertNextPoint( 1, 0, -1 );
    points->InsertNextPoint( -1, 0, -1 );


    vtkSPtrNew( plane, vtkPlane );
    plane->SetOrigin( 0, 2, 0 );
    plane->SetNormal( 0, -1, 0 );


    // ==================== start to generate cube ====================
    for( int i = 0; i < 4; ++i )
    {
        Point projectPt = Point( points->GetPoint( i ) );
        plane->ProjectPoint( projectPt.point, projectPt.point );
        points->InsertNextPoint( projectPt.point );
    }


    vtkSPtrNew( cells, vtkCellArray );
    vtkIdType bottom_ptIds1[3] = { 2, 1, 0 };
    cells->InsertNextCell( 3, bottom_ptIds1 );
    vtkIdType bottom_ptIds2[3] = { 0, 3, 2 };
    cells->InsertNextCell( 3, bottom_ptIds2 );


    vtkIdType top_ptIds1[3] = { 5, 6, 4 };
    cells->InsertNextCell( 3, top_ptIds1 );
    vtkIdType top_ptIds2[3] = { 4, 6, 7 };
    cells->InsertNextCell( 3, top_ptIds2 );


    vtkIdType left_ptIds1[3] = { 0, 4, 3 };
    cells->InsertNextCell( 3, left_ptIds1 );
    vtkIdType left_ptIds2[3] = { 7, 3, 4 };
    cells->InsertNextCell( 3, left_ptIds2 );


    vtkIdType right_ptIds1[3] = { 5, 2, 6 };
    cells->InsertNextCell( 3, right_ptIds1 );
    vtkIdType right_ptIds2[3] = { 1, 2, 5 };
    cells->InsertNextCell( 3, right_ptIds2 );


    vtkIdType front_ptIds1[3] = { 0, 1, 4 };
    cells->InsertNextCell( 3, front_ptIds1 );
    vtkIdType front_ptIds2[3] = { 1, 5, 4 };
    cells->InsertNextCell( 3, front_ptIds2 );


    vtkIdType back_ptIds1[3] = { 6, 7, 2 };
    cells->InsertNextCell( 3, back_ptIds1 );
    vtkIdType back_ptIds2[3] = { 2, 7, 3 };
    cells->InsertNextCell( 3, back_ptIds2 );


    vtkSPtrNew( result, vtkPolyData );
    result->SetPoints( points );
    result->SetPolys( cells );
    result->BuildCells();
    result->BuildLinks();
    result->Modified();
    // ==================== Finish: cube ====================


    vtkSPtrNew( mapper, vtkPolyDataMapper );
    mapper->SetInputData( result );


    vtkSmartPointer<vtkSTLWriter> writer = vtkSmartPointer<vtkSTLWriter>::New();
    writer->SetFileName( "cube.stl" );
    writer->SetInputData( result );
    writer->Write();


    vtkSPtrNew( actor, vtkActor );
    actor->SetMapper( mapper );


    vtkSPtrNew( renderer, vtkRenderer );
    renderer->AddActor(actor);
    renderer->SetBackground( 0, 0, 0 );


    vtkSPtrNew( renderWindow, vtkRenderWindow );
    renderWindow->AddRenderer( renderer );


    vtkSPtrNew( renderWindowInteractor, vtkRenderWindowInteractor );
    renderWindowInteractor->SetRenderWindow( renderWindow );


    renderer->ResetCamera();
    renderWindow->Render();
    renderWindowInteractor->Start();

    return 0;
}

The code for display bad cells:

    // use point locator to draw it ===================
    double bounds[6];
    result->ComputeBounds();
    result->GetBounds( bounds );

    vtkNew<vtkPoints> samplePoints;
    vtkNew<vtkCellArray> sampleCells;
    vtkNew<vtkPolyData> samplePolyData;

    vtkNew<vtkPointLocator> locator;
    locator->InitPointInsertion( samplePoints, bounds );
    std::cout << "points size: " << samplePoints->GetNumberOfPoints() << std::endl;

    for( int i = 0; i < modifyCellIds.size(); ++i )
    {
        int cellId = modifyCellIds[i];
        vtkNew<vtkIdList> ptIds;
        result->GetCellPoints( cellId, ptIds );
        vtkIdType newCell[3];
        for( int j = 0; j < ptIds->GetNumberOfIds(); ++j )
        {
            double ptPos[3];
            result->GetPoint( ptIds->GetId( j ), ptPos );
            locator->InsertUniquePoint( ptPos, newCell[j] );
        }
        sampleCells->InsertNextCell( 3, newCell );
    }
    cout << "points size: " << samplePoints->GetNumberOfPoints() << endl;
    cout << "sampleCells size: " << sampleCells->GetNumberOfCells() << endl;

    samplePolyData->SetPoints( samplePoints );
    samplePolyData->SetPolys( sampleCells );
    samplePolyData->BuildCells();
    samplePolyData->BuildLinks();
    // finish: draw =====================

    vtkSPtrNew( sampleMapper, vtkPolyDataMapper );
    sampleMapper->SetInputData( samplePolyData );


    vtkSPtrNew( sampleActor, vtkActor );
    sampleActor->SetMapper( sampleMapper );
    sampleActor->GetProperty()->SetColor( 1, 0, 0 );
    // ================ finished =================

The code for re-order points in bad cells:

    // ------------- start -------------
    std::vector<int> modifyCellIds;
    Point center( result->GetCenter() );
    for( int i = 0; i < result->GetNumberOfCells(); ++i )
    {
        vtkIdType npts;
        vtkIdType *ptIds;
        result->GetCellPoints( i, npts, ptIds );
        
        Point pt0( result->GetPoint( ptIds[0] ) );
        Point pt1( result->GetPoint( ptIds[1] ) );
        Point pt2( result->GetPoint( ptIds[2] ) );
        Point vec1 = pt1 - pt0;
        Point vec2 = pt2 - pt1;
        Point vec = vec1 ^ vec2;
        vec.Unit();
        
        Point ptsCenter = (pt0 + pt1 + pt2)/3.0;
        Point __vec = ptsCenter - center;
        if( vec.Dot( __vec ) < 0 )
        {
            modifyCellIds.push_back( i );
        }
    }
    for( int i = 0; i < modifyCellIds.size(); ++i )
    {
        int cellId = modifyCellIds[i];
        vtkIdType npts;
        vtkIdType *ptIds;
        result->GetCellPoints( cellId, npts, ptIds );
        vtkIdType tri[3] = { ptIds[2], ptIds[1], ptIds[0] };
        result->ReplaceCell(cellId, 3, tri);
    }    
    // ----------- finished ---------------
Categories: ToolWeb

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments

XOR Strings
: Input your strings, the tool can encrypt and decrypt them.

X
0
Would love your thoughts, please comment.x
()
x