Retrieve the World Rotation of a Selected Edge?



  • Hi,

    I'm trying to align a window on a wall. But the wall is angled and I'm having a problem determining the proper orientation.
    You can see an illustration of problem here:
    https://www.dropbox.com/s/j6rqbvokopn3b6h/c4d084_align_angled_rotation_properly.mp4?dl=0

    I was thinking of getting the world rotation of the selected edge, but the coordinate manager does not seem to show anything. You can see the attempt here:
    https://www.dropbox.com/s/z03x7faykja0u9c/c4d084_align_angled_rotation_properly.jpg?dl=0

    Is there a way to retrieve it using Python?

    Thank you for looking at the problem



  • Hi @bentraje,

    do you need that functionality to work in GUI mode? If so, here's an example video showing that Cinema 4D already provides that funtionality - a bit hidden though:
    https://www.youtube.com/watch?v=SuH91wohs9w

    In P/S/R tool with a selected object, Ctrl+RightClick an axis (or rotation band). Release both to hover over a reference point, edge, axis, etc.
    Left-Click and drag to a target point.

    Another workaround I also use often, are guides. Set a guide to semi-line, so you have start - and end-handles. Snap the guide to the edge or angled wall.
    Now you can either use Guide-Snapping or simply copy/paste the rotation.

    The third solution would be to use dynamic guides.

    Best,
    Robert



  • Thanks @mp5gosu for the illustration. Works as expected.



  • hello,

    To answer this question if someone want to do it by code.

    import c4d
    from c4d import gui
    
    # Welcome to the world of Python
    
    
    # Main function
    def main():
        #get the selected object
        op = doc.GetActiveObject()
        if not op:
            raise TypeError("there's no object selected")
        if not op.IsInstanceOf(c4d.Opolygon):
            raise TypeError("obj should be a polygon object")
    
        #setup neighbor
        nbr = c4d.utils.Neighbor()
        nbr.Init(op)
    
        #get the selected edge
        bs = op.GetSelectedEdges(nbr,c4d.EDGESELECTIONTYPE_SELECTION)
        
    
        #maximum number of edge should be number of polygon * 4
        sel = bs.GetAll(op.GetPolygonCount() * 4)
        
        #get all polygon
        vadr = op.GetAllPolygons()
        #init point a and b index to -1 for error check
        a = b = -1
        #initialise a counter to check in sel array.
        countEdge = 0
        
        #we can check now every edge to find the corresponding points. So for each polygon
        for i in xrange(op.GetPolygonCount()):
            #get the polygon information
            pli = nbr.GetPolyInfo(i)
    
            for side in xrange(4): # Test all 4 sides of a polygon
                # Only proceed if edge is marked
                # and edge really exists (for triangles side 2 from c..d does not exist as c==d)
    
                if pli["mark"][side] or (side==2 and vadr[i].c == vadr[i].d): 
                    continue 
                
                #if the edge is marked as selected in our sel array
                if sel[countEdge]:
                    if side==0:
                        a=vadr[i].a; b=vadr[i].b
                    elif side==1:
                        a=vadr[i].b; b=vadr[i].c
                    elif side==2:
                        a=vadr[i].c; b=vadr[i].d
                    elif side==3:
                        a=vadr[i].d; b=vadr[i].a
                countEdge +=1
    
        if a == -1 or b == -1:
            raise ValueError("points index can't be negatives")
        
        #get all points array 
        points = op.GetAllPoints()
    
        
        #Get the direction of the edge in global coordinate (multiply the points'vector by the matrix of the object)
        opmg = op.GetMg()
        #i've picked a direction from point a to point b so the angle could need to be reverted.
        dirVector = points[b]*opmg - points[a]*opmg
        #normalize a vector is often a good idea.
        dirVector.Normalize()
        
        #transform the vector to hpb note the result is in radian
        hpb = c4d.utils.VectorToHPB(dirVector)
        
        #transform radian to degree
        hpb.x = c4d.utils.RadToDeg(hpb.x)    
        hpb.y = c4d.utils.RadToDeg(hpb.y)
        hpb.z = c4d.utils.RadToDeg(hpb.z)
    
        print "the edge is poiting to",dirVector,"the corresponding angle is", hpb
    
    
    # Execute main()
    if __name__=='__main__':
        main()
    

    Cheers
    Manuel


Log in to reply