Getting points from polygons (Without duplicates)



  • On 14/06/2014 at 15:55, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   13 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    Example:
    Grab polygon[0] and get the 4 point ID#s.
    Now grab polygon[1] and get the 4 point ID#s.

    Since the two polygons share an edge. Two points will show up twice in your results.
    The more polygons you have...The more duplicate values you get.
    And if you use these values in your code. You get double transformations for those duplicate points. 😢

    Right now I'm storing all the points in an array. And using a nested for() loop to delete duplicate ID#s from. It works but it's slower than molasses on a winter's day.
    Even using a std::Vector array is very, very slow.

    Is there no way to mark the 4 points as you loop through the polygons. So that you can skip over them and not record them into an array in the next iterations of the loop?

    -ScottA



  • On 14/06/2014 at 21:22, xxxxxxxx wrote:

    You need to look at Neighbor and PolyInfo.  The duplicate points are 'marked' when using these classes to traverse polygons, edges, and vertices.



  • On 15/06/2014 at 07:43, xxxxxxxx wrote:

    Hi Robert,

    I've been trying to use that. But I'm having trouble with it.
    I'm just checking verts. if they are marked. And if they aren't I save their ID# into an array.
    But I'm not getting the proper results. Only a few verts. are being saved to the array.

    Then I started to wonder if the reason it's not working is because the marking stuff and PolyInfo was only for edges?
    In the docs all I'm seeing is: face[4], edge[4], mark[4].
    Nothing about marking vertices of a polygon.

    How would I use this class to mark vertices?

    -ScottA



  • On 15/06/2014 at 11:12, xxxxxxxx wrote:

    Oh yes.  Only the coincidental edges between polygons are marked.  Sorry about that.

    Create a cleared (zeroed) bool array the size of GetPointCount() and 'mark' (set to TRUE) each point (by index into its Vector array as given by the polygon references a,b,c,d) as you encounter them in the polygon  (the same point shared by multiple polygons has the same index value across polygons).  If the array value at that index is TRUE, then do nothing and move on.  Otherwise, set it to TRUE and do your transform.  This eliminates the need to preprocess duplicated altogether and should be fast as a waterfall in summer.  This method should be exponentially faster as it skips duplicates without having to ever traverse the entire point ID set.



  • On 15/06/2014 at 12:18, xxxxxxxx wrote:

    Thanks Robert.
    I think I understand you're saying. But I'm having trouble implementing it.
    I think I'm mostly confused about how to fill the array with TRUE values.

        PolygonObject *obj = (PolygonObject* ) doc->GetActiveObject();  
      if (!obj) return FALSE;  
      if (!obj || obj->GetType() != Opolygon) return FALSE;  
      
      CPolygon *polys = obj->GetPolygonW();  
      BaseSelect *selected_polys = obj->GetPolygonS();  
      LONG pntCount = obj->GetPointCount();  
      
      //This array will be used to store the marked(TRUE/FALSE) state of a vertice  
      GeDynamicArray<Bool>markedPnts(pntCount);  
      
      //Get the selected polygons and then get their four verts(a,b,c,d) ID#s  
      for(LONG i=0; i<pntCount; i++)  
      {  
          if(selected_polys->IsSelected(i))  
          {  
              LONG A = polys->a;  
              LONG B = polys->b;      //Get the four ID#s for the four points in each polygon  
              LONG C = polys->c;  
              LONG D = polys->d;  
      
              markedPnts[i] = TRUE;  //<--I'm doing this wrong! How do I fill the array?  
      
              if(markedPnts[i] = TRUE)  
              {  
                  //transform the point  
              }  
          }  
      
          if(markedPnts[i] == TRUE) GePrint(LongToString(markedPnts[i]));  
      }
    

    -ScottA



  • On 15/06/2014 at 13:43, xxxxxxxx wrote:

    PolygonObject *obj = (PolygonObject* ) doc->GetActiveObject();
    if (!(obj && (obj->GetType() == Opolygon))) return FALSE;
      
    CPolygon *polys = obj->GetPolygonW();
    if (!polys)	return FALSE;
    BaseSelect *selected_polys = obj->GetPolygonS();
    if (!(selected_polys && selected_polys->GetCount()))	return FALSE;
      
    LONG pntCount = obj->GetPointCount();
    if (!pntCount)	return FALSE;
      
    //This array will be used to store the marked(TRUE/FALSE) state of a vertice
    // NOTE: Check that this array is cleared.
    //   If not, you will need to pre-zero the elements (set all to FALSE)
    GeDynamicArray<Bool>markedPnts(pntCount);
      
    //Get the selected polygons and then get their four verts(a,b,c,d) ID#s
    CPolygon*	p;
    LONG			a, b, c, va, vb, vc, vd;
    // Loop through selected segments
    for (LONG seg = 0L; selected_polys->GetRange(seg, &a, &b); ++seg)
    {
    	// Loop through segment 'seg' from a to b
    	for (c = a; c <= b; ++c)
    	{
    		p =	&polys[c];
    		va =	p->a;
    		vb =	p->b;
    		vc =	p->c;
    		vd =	p->d;
    		if (markedPnts[va] == FALSE)
    		{
    			// transform the point
    			markedPnts[va] = TRUE;
    		}
    		if (markedPnts[vb] == FALSE)
    		{
    			// transform the point
    			markedPnts[vb] = TRUE;
    		}
    		if (markedPnts[vc] == FALSE)
    		{
    			// transform the point
    			markedPnts[vc] = TRUE;
    		}
    		if (markedPnts[vd] == FALSE)
    		{
    			// transform the point
    			markedPnts[vd] = TRUE;
    		}
    	}
    }
    


  • On 15/06/2014 at 13:50, xxxxxxxx wrote:

    The cool thing is that if the polygon is a triangle (c == d), then the last condition does not incur more unwanted transformation of a particular vertex point (twice on the same polygon).  Each unique vertex will only be transformed once.



  • On 15/06/2014 at 14:53, xxxxxxxx wrote:

    Thank You sir. 🍺
    I think this will work nicely for me.

    -ScottA


Log in to reply