point coordinates from selected polygon [SOLVED]



  • On 18/02/2015 at 23:12, xxxxxxxx wrote:

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

    ---------
    Hi

    I am beginner of C++. I want to know how can I get point coordinates from the selected polygon.
    I do know how to do that with coffee.

    main(doc,op)
    {
    var tg_obj= doc->GetFirstObject();
    if(!instanceof(tg_obj,PolygonObject)) return FALSE;

    var pnt_array= tg_obj->GetPoints();
    
    var poly_cnt= tg_obj->GetPolygonCount();
    var poly_array= tg_obj->GetPolygons();
    var sel_poly= tg_obj->GetPolygonSelection();
    var sel_numpoly= sel_poly->GetCount();
    
    
    if(sel_numpoly==0) {
    	println("no selected polygon");
    	return FALSE;
    	}
    
    
    var i= 0;
    while(!sel_poly->IsSelected(i)) i++;
    
    var a= poly_array[i\*4 + 0];
    var b= poly_array[i\*4 + 1];
    var c= poly_array[i\*4 + 2];
    var d= poly_array[i\*4 + 3];
    
    println(pnt_array[a],"   ",pnt_array **,"   ",pnt_array[c],"   ",pnt_array[d]);
    
    return;
    

    }

    Dose anyone know about how should I code with C++ to get point coordinates ?

    Best wishes
    shortail



  • On 19/02/2015 at 02:45, xxxxxxxx wrote:

    Hi shortail,

    here's some pseudo code that might help get you started:

      
    BaseDocument *doc = GetActiveDocument();   
    BaseObject *obj = doc->GetFirstObject();   
      
    if(obj == NULL)   
    {   
         return;   
    }   
    else if(obj->GetType() != Opolygon) // Otype being the object type, see docs for types   
    {   
         return;   
    }   
      
    PointObject *p_obj = (PointObject* )obj;   
    Vector *points = p_obj->GetPointR();   
      
    for(int i = 0; i <= p_obj->GetPointCount()-1;)   
    {   
         GePrint("Point " + LongToString(i) + "'s xyz: " + RealToString(points[i].x) + "," + RealToString(points[i].y) + "," + RealToString(points[i].z));   
      
         i++;   
    }   
    

    Hope that's of some help!

    WP.



  • On 19/02/2015 at 11:22, xxxxxxxx wrote:

    Hi WickedP

    Thank you for replaying for my question. 
    I could understand How can I get all of point coordinates included in the targeted polygon object.
    if there is a certain polygon selected in the polygon object, How can I describe the code to obtain those point coordinates from the selected polygon ?

    Thank you for your help

    shortail



  • On 19/02/2015 at 17:27, xxxxxxxx wrote:

    if (!obj)
    	return;
    if (obj->GetType() != Opolygon)  // Otype being the object type, see docs for types
         return;
      
    PolygonObject*	pobj =	ToPoly(obj);
    BaseSelect* bs = pobj->GetPolygonS();	// Gets currently selected polygons by index
    CPolygon* polys = pobj->GetPolygonR();
    Vector* points = pobj->GetPointR();
      
    CPolygon* p = NULL;
    Vector	vA, vB, vC, vD;
    LONG a, b;
    for (LONG i = 0L; bs->GetRange(i,&a,&b); ++i)
    {
    	for (; a<=b; ++a)
    	{
    		// For each selected polygon
    		// get vertices a, b, c, optionally d
    		p = &polys[a];
    		vA = points[p->a];
    		vB = points[p->b];
    		vC = points[p->c];
    		// if polygon is a quadrangle, not a triangle
    		if (p->c != p->d)
    			vD = points[p->d];
    	}
    }
    

    If you want to store all of the point vectors for the selected polygons, you should first get the number of them (LONG cnt = bs->GetCount()) and allocate a Vector array (cnt*4) size.  Then fill that linearly.  Note that you most likely will have duplicate vectors since polygons share points.



  • On 19/02/2015 at 17:40, xxxxxxxx wrote:

    Hi shortail,

    EDIT: ah - Robert's beaten me too it!

    I may have mis-read what you are trying to do. My apologies.

    In the docs there's a CPolygon object container. This is an array of polygons from 0-X index. Each index has 4 numbers (a,b,c,d). These numbers are the points that make up your polygon. If your polygon is triangular, d = c (i.e. c and d are in the same place).

    Once you get these points, you can then use these points on your point array, which will give you your co-ordinates.

      
    BaseObject *obj = ...;   
    PolygonObject *p_obj = (PolygonObject* )obj;   
    CPolygon *Polys = p_obj->GetPolygonR();   
      
    // # = selected polygon index   
    // to get polygon's first point, use: Polys[#].a   
      
    // lets assume x is polygon 3   
                      
    Vector *points = p_obj->GetPointR();   
      
    // to get x co-ordinate, use: points[Polys[3].a].x   
      
    GePrint("Polygon 3's first point is at: " + RealToString(points[Polys[3].a].x) + "," + RealToString(points[Polys[3].a].y) + "," + RealToString(points[Polys[3].a].z));   
    

    Something like that anyway.

    WP.



  • On 20/02/2015 at 23:05, xxxxxxxx wrote:

    Hi Guys,

    Thank you very much for telling me how to get point coordinates from certain selected polygon.
    now, I am wanting to know little bit of detail about How is those point coordinates stored in my own array.
    below is the code I describe to store point coordinates obtained from selected polygon into array.

    BaseObject\* tg_obj= doc->GetActiveObject();
    if(!tg_obj || tg_obj->GetType()!=Opolygon) return FALSE;
    
    
    PolygonObject\* tg_pobj= ToPoly(tg_obj);
    BaseSelect\* bs= tg_pobj->GetPolygonS();
    CPolygon\* polys= tg_pobj->GetPolygonW(); 
    Int32 poly_cnt= tg_pobj->GetPolygonCount();
    Vector\* points= tg_pobj->GetPointW(); 
    Int32 cnt_sel= bs->GetCount();
    
    
    
    CPolygon\* p= NULL;
    maxon::BaseArray<Vector> MyArray;
    MyArray.Resize(4\*cnt_sel);
    Vector vA, vB, vC, vD;
    //Int32 a, b;
    Int32 i, k=0, j;
    
    
    for(i= 0;i<poly_cnt; i++)
    {
    	if(bs->IsSelected(i))
    	{
    		p= &polys _; // if IsSelected were used, a should be i
    		vA= points[p->a];
    		vB= points[p->b];
    		vC= points[p->c];
    		vD= points[p->d];
    
    		MyArray[k\*4 + 0]= points[p->a];
    		MyArray[k\*4 + 1]= points[p->b];
    		MyArray[k\*4 + 2]= points[p->c];
    		MyArray[k\*4 + 3]= points[p->d];
    		k++;
    		
    	}
    }
    

    Are there any idea to have better code ?

    Best

    Shortail



  • On 20/02/2015 at 23:39, xxxxxxxx wrote:

    1. The code that I presented is the optimal way to traverse BaseSelects.  Use that paradigm!

    2. As noted, you will need to include conditions and circumstantial code to consider duplicate vector points.  Note that you only need to consider the vector index (as they will be identical polygon to polygon despite the 'a,b,c,d' reference).  The 'a,b,c,d' references are into the Vector array.

    3. You should really consider all conditions to avoid repetition. While the simplicity of the code you present appears easy and fast, conditions will more quickly avoid repetition in storage and checks.  Do not expect that storing all values linearly will be faster than not storing already stored values by checking for such.  While it may appear antithetical, early termination in a loop on condition can improve performance greatly (BigO(v^2) to BigO(lgV)) which is significant!



  • On 25/02/2015 at 00:14, xxxxxxxx wrote:

    Hi Robert,

    I am so sorry for being late saying thank you for answering my question.
    I am spending and thinking to understand about the code you presented last time.

    I have couple question for you.

    Q1) GetRange(i,&a,&b) does not work

    when I use this function, I get compiler error and Compiler always say "too a few parameters". as far as I looked at C++ SDK, it seems that we need to use one more parameter, which is a maxElements. Do I need to use the parameter ?

    And also I tried code below....

    BaseObject* tg_obj= doc->GetActiveObject();
    if(tg_obj||tg_obj->GetType()!=Opolygon) return FALSE;

    PolygonObject\* tg_pobj= ToPoly(tg_obj);
    BaseSelect\* bs= tg_pobj->GetPolygonS();
    CPolygon\* polys= tg_pobj->GetPolygonW(); // create polygon array
    Vector\* points= tg_pobj->GetPointW();
    Int32 poly_cnt= tg_pobj->GetPolygonCount();
    
    
    CPolygon\* p= NULL;
    Vector vA, vB, vC, vD;
    
    
    Int32 seg=0, i, a, b;
    for(i= 0; bs->GetRange(i,poly_cnt,&a,&b); i++) // please note this code, I add one more parameter 
    {
    	for(i=a; i<=b; ++i)
    	{
    		p= &polys _;
    		vA= points[p->a];
    		vB= points[p->b];
    		vC= points[p->c];
    		if(p->c != p->d){
    
    
    		vD= points[p->d];
    		}
    	}
    }
    
    
    GePrint(String::VectorToString(vA));
    GePrint(String::VectorToString(vB));
    GePrint(String::VectorToString(vC));
    GePrint(String::VectorToString(vD));
    

    but, this code is not working at all, Are there anything wrong ?

    Q2) How Can I make the condition to avoid storing point coordinates that was already stored ?
    if you gave me hints, I would appreciate you.

    I am sorry for asking too many things, I am just beginner of C++.

    Thank you very much.

    Shortail.



  • On 25/02/2015 at 17:14, xxxxxxxx wrote:

    In later C4D versions, yes, the GetRange() has an added argument parameter.  Instead of using poly_cnt, I would use a separate variable max_poly = poly_cnt-1 in GetRange().

    You might want to do your prints inside a for loop.  Your initial conditional will fail.  It should be if (!tg_obj||tg_obj->GetType() != Opolygon).  Again, if you want to store *all* of the points of *all* of the selected polygons, you should do something like this:

    BaseObject* obj = doc->GetActiveObject();
    if (!(obj && (obj->GetType() == Opolygon)))  // Both conditions must be TRUE
         return FALSE;
      
    PolygonObject*	pobj =	ToPoly(obj);
    BaseSelect* bs = pobj->GetPolygonS();	// Gets currently selected polygons by index
      
    Int32 num_ppts = bs->GetCount()*4L;
    Vector* ppts = bNew Vector[num_ppts];	// Not sure if its brackets or parentheses
    if (!ppts)
    	return FALSE;
      
    Vector* p_ppts = ppts;
    CPolygon* polys = pobj->GetPolygonR();
    Vector* points = pobj->GetPointR();
    Int32 max_p = pobj->GetPolygonCount()-1L;
    CPolygon* p = NULL;
    Int32 a, b;
    for (LONG i = 0L; bs->GetRange(i,max_p,&a,&b); ++i)
    {
    	for (; a<=b; ++a)
    	{
    		// For each selected polygon
    		// get vertices a, b, c, optionally d
    		p = &polys[a];
    		*p_ppts = points[p->a];
    		++p_ppts;
    		*p_ppts = points[p->b];
    		++p_ppts;
    		*p_ppts = points[p->c];
    		++p_ppts;
    		*p_ppts = points[p->d];
    		++p_ppts;
    	}
    }
      
    // Do something with 'ppts'
    for (LONG i = 0L; i != num_ppts; ++i)
    	GePrint(String::VectorToString(ppts[i]));
    //....
    


  • On 26/02/2015 at 23:44, xxxxxxxx wrote:

    Thanks, Robert.

    it seem like bNew is not om the list of C++ SDK. instead of this, I used BaseArray function like below.

    BaseObject* obj = doc->GetActiveObject();
    if (!(obj && (obj->GetType() == Opolygon)))  // Both conditions must be TRUE
         return FALSE;

    PolygonObject* pobj = ToPoly(obj);
    BaseSelect* bs = pobj->GetPolygonS(); // Gets currently selected polygons by index

    Int32 num_ppts = bs->GetCount()*4L;

    maxon::BaseArray<Vector> ppts;
    ppts.Resize(num_ppts); // Not sure if its brackets or parentheses
    if (!num_ppts)
    return FALSE;

    CPolygon* polys = pobj->GetPolygonW();
    Vector* points = pobj->GetPointW();
    Int32 max_p = pobj->GetPolygonCount()-1L;
    CPolygon* p = NULL;
    Int32 a, b, k= 0;
    for (Int32 i = 0L; bs->GetRange(i,max_p,&a,&b); ++i)
    {
    for (; a<=b; ++a)
    {
    // For each selected polygon
    // get vertices a, b, c, optionally d
    p = &polys[a];
    ppts[k*4 + 0] = points[p->a];

    	ppts[k\*4 + 1] = points[p->b];
    	
    	ppts[k\*4 + 2] = points[p->c];
    	
    	ppts[k\*4 + 3] = points[p->d];
    	k++;
    }
    

    }

    // Do something with 'ppts'
    for (Int32 i = 0L; i != num_ppts; ++i){

    GePrint(String::VectorToString(ppts _));
    

    }

    Actually I have often seen someone who use bNew to create new array,  what version of C4D you guys are using ?



  • On 27/02/2015 at 06:04, xxxxxxxx wrote:

    gNew/gDelete/bNew/bDelete appear to have been made deprecated in R15.  I haven't transitioned code to R16 since my plugins still support R13 onward.  Basically, impractical for me to update my code to R16.  It would take literally months to make the changes required and no more backward compatibility to boot.

    I hope this helped you get going.  If you need to retain only unique vertices, you could store by index (p->a) and check for duplicates as you store them.  It will be slower thereby.  Then you would use pobj->GetPointW() and use the indices you stored to access the vectors themselves.



  • On 01/03/2015 at 02:53, xxxxxxxx wrote:

    Thanks, Robert. I appreciate you !



  • On 01/03/2015 at 22:34, xxxxxxxx wrote:

    Hi,

    I'll assume by the way the thread evolved, and especially by the last posting, that it is ready to be labelled solved, but will leave it open for any further related postings.

    Joey Gaspe
    SDK Support Engineer


Log in to reply