Skip to content

Point coordinates get lost #1482

@Squirrel8475

Description

@Squirrel8475

Minimal example

The minimal example starts from a list of (x, y, z) coordinates,. Then converts it to a list of gp_Pnt, via a Collection, and stores the list in self.pnts. When the list is recalled at a later stage in the code, some coordinates are incorrect.

py 3.11.10 | packaged by conda-forge [MSC v.1941 64 bit (AMD64)]
OCC.VERSION '7.9.0'

# -*- coding: utf-8 -*-
import numpy as np
from OCC.Core.gp import gp_Pnt
from OCC.Core.TColgp import TColgp_Array1OfPnt
#==============================================================================
class Minimal_Example():
#==============================================================================
    def __init__(self):
        self.pnts=None
        self.inputs=dict()
        self.inputs['variant']={'opt':0}
        self.inputs['trim']={'skip':False,'by':2}
#------------------------------------------------------------------------------
    def pack_list(self):
        
        # Load point coordinates
        np_array1 = np.array([
             [26.0, 12.0, -1.0],
             [2.0, 11.0, 1.0],
             [0.0, 12.0, 3.0],
             [6.0, 13.0, 6.0],
             [2.0, 15.0, 7.0],
             [9.0, 17.0, 10.0],
             [16.0, 20.0, 12.0],
             [14.0, 22.0, 15.0],
             [7.0, -26.0, 19.0],
             [12.0, 28.0, 22.0],
             [2.0, 1.0, 25.0],
             [5.0, 12.0, 33.0],
             [3.0, 4.0, 5.0],
             [-4.0, 9.0, -1.0],
             [2.1, 3.0, 11.0]
            ],float)

        nrows= np_array1.shape[0]
        
        # Vary number of points for the purpose of debugging, can be ignored at this stage
        if not self.inputs['trim']['skip']:
            by=self.inputs['trim']['by']
            np_array1 = np_array1[0:(nrows-by),:]
            nrows= np_array1.shape[0]
 
        opt=self.inputs['variant']['opt']
        if opt==0:
            # Original user code, this is the case of interest
            # - convert np_arr to occ_arr
            # - user code
            # - convert occ_arr to list 
            #
            # Please note that attention was paid to start the OCC array index
            # to one and not zero like in Python.
            occ_arr1   = TColgp_Array1OfPnt(1,nrows)
            istart     = occ_arr1.Lower()  
            iend       = occ_arr1.Upper()
            inpy=0
            for iocc in range(istart,iend+1):
                coord     = np_array1[inpy,:].tolist()
                occ_arr1.SetValue(iocc,gp_Pnt(*coord))
                inpy=inpy+1
            
            # [... User code here removed for the sake of minimal example...]
            
            # Convert pyOCC array of gp_Pnt to Python list of gp_Pnt
            self.pnts=list()
            for iocc in range(istart,iend+1):
                a_gp_pnt = occ_arr1.Value(iocc) 
                self.pnts.append(a_gp_pnt)
                
        elif opt==1:
           # If there would be no user code in the middle, the code could be  simplified by going straightaway from
           # np_arr to occ_arr. In that case, the problem seen at later stage would not appear.But it cannot be considered 
           # as a solution, as the user code removed for the sake of debugging is needed.
            self.pnts=list()
            for inpy in range(0,nrows):
                coord     = np_array1[inpy].tolist()
                a_gp_pnt = gp_Pnt(*coord)
                self.pnts.append(a_gp_pnt)
        
        # Pack the points in the list and print the coordinates to check that eveything is correct up to that point. 
        print('\n===')
        print('*Packed %s point(s), check coords:' % str(nrows))
        print([x.Coord() for x in self.pnts])
#------------------------------------------------------------------------------
    def unpack_list(self):
        # Unpack the list here, and check coordinates. The problem is visible at this stage, some coordinates are wong
        #
        # What is wrong: the coordinates x and y of the first point, receive a tiny value '1e-311'.
        # Only x,y are incorrect, but z is correct. And only first point is wrong, others are OK        
        print('\n*Unpacked, check coords:')
        print([x.Coord() for x in self.pnts ])
#------------------------------------------------------------------------------
    def run(self):
        self.pack_list()
        self.unpack_list()
#==============================================================================

print('\n===== Reproduce the issue')
debugger0 = Minimal_Example()
debugger0.inputs['variant']['opt']=0
debugger0.inputs['trim']['skip']=False
debugger0.inputs['trim']['by']=3
debugger0.run() 

The output is shown below.
*Packed 12 point(s), check coords:
[(26.0, 12.0, -1.0), (2.0, 11.0, 1.0), (0.0, 12.0, 3.0), (6.0, 13.0, 6.0), (2.0, 15.0, 7.0), (9.0, 17.0, 10.0), (16.0, 20.0, 12.0), (14.0, 22.0, 15.0), (7.0, -26.0, 19.0), (12.0, 28.0, 22.0), (2.0, 1.0, 25.0), (5.0, 12.0, 33.0)]

*Unpacked, check coords:
[(1.131783611129e-311, 1.1318068432973e-311, -1.0), (2.0, 11.0, 1.0), (0.0, 12.0, 3.0), (6.0, 13.0, 6.0), (2.0, 15.0, 7.0), (9.0, 17.0, 10.0), (16.0, 20.0, 12.0), (14.0, 22.0, 15.0), (7.0, -26.0, 19.0), (12.0, 28.0, 22.0), (2.0, 1.0, 25.0), (5.0, 12.0, 33.0)]

The formatting in bold points to the values which are wrong.

Additional tests

  • Moving from opt 0 to 1. The problem disappears but as commented in the code it cannot be accepted as a solution
for opt in [0,1]:
    debugger0 = Minimal_Example()
    debugger0.inputs['variant']['opt']=opt
    debugger0.inputs['trim']['skip']=False
    debugger0.inputs['trim']['by']=3
    debugger0.run()  
  • Changing the number of points. This is the most surprising, the problem occurs when the inputs contains 12 points.
    It just works fine with more or less points. To change the number of points, just set the by parameters to the number of
    elements to be removed from the original list.
for by in range(0,14):
    debugger0 = Minimal_Example()
    debugger0.inputs['variant']['opt']=0
    debugger0.inputs['trim']['skip']=False
    debugger0.inputs['trim']['by']=by
    debugger0.run()   

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions