Help converting from C to Python!

If it’s not pushing to hard, can someone help me converting this C code to Python, please?
I’ll thank you alot!!


typedef struct {
   double x,y,z;
} XYZ;

/*
   Calculate the line segment PaPb that is the shortest route between
   two lines P1P2 and P3P4. Calculate also the values of mua and mub where
      Pa = P1 + mua (P2 - P1)
      Pb = P3 + mub (P4 - P3)
   Return FALSE if no solution exists.
*/
int LineLineIntersect(
   XYZ p1,XYZ p2,XYZ p3,XYZ p4,XYZ *pa,XYZ *pb,
   double *mua, double *mub)
{
   XYZ p13,p43,p21;
   double d1343,d4321,d1321,d4343,d2121;
   double numer,denom;

   p13.x = p1.x - p3.x;
   p13.y = p1.y - p3.y;
   p13.z = p1.z - p3.z;
   p43.x = p4.x - p3.x;
   p43.y = p4.y - p3.y;
   p43.z = p4.z - p3.z;
   if (ABS(p43.x)  < EPS && ABS(p43.y)  < EPS && ABS(p43.z)  < EPS)
      return(FALSE);
   p21.x = p2.x - p1.x;
   p21.y = p2.y - p1.y;
   p21.z = p2.z - p1.z;
   if (ABS(p21.x)  < EPS && ABS(p21.y)  < EPS && ABS(p21.z)  < EPS)
      return(FALSE);

   d1343 = p13.x * p43.x + p13.y * p43.y + p13.z * p43.z;
   d4321 = p43.x * p21.x + p43.y * p21.y + p43.z * p21.z;
   d1321 = p13.x * p21.x + p13.y * p21.y + p13.z * p21.z;
   d4343 = p43.x * p43.x + p43.y * p43.y + p43.z * p43.z;
   d2121 = p21.x * p21.x + p21.y * p21.y + p21.z * p21.z;

   denom = d2121 * d4343 - d4321 * d4321;
   if (ABS(denom) < EPS)
      return(FALSE);
   numer = d1343 * d4321 - d1321 * d4343;

   *mua = numer / denom;
   *mub = (d1343 + d4321 * (*mua)) / d4343;

   pa->x = p1.x + *mua * p21.x;
   pa->y = p1.y + *mua * p21.y;
   pa->z = p1.z + *mua * p21.z;
   pb->x = p3.x + *mub * p43.x;
   pb->y = p3.y + *mub * p43.y;
   pb->z = p3.z + *mub * p43.z;

   return(TRUE);
}


from math import abs

class XYZ:
    def __init__(self):
        self.x = 0.0
        self.y = 0.0
        self.z = 0.0


##   Calculate the line segment PaPb that is the shortest route between
##   two lines P1P2 and P3P4. Calculate also the values of mua and mub where
##      Pa = P1 + mua (P2 - P1)
##      Pb = P3 + mub (P4 - P3)
##   Return FALSE if no solution exists.

def LineLineIntersect(
    p1,p2,p3,p4,pa,pb,
    mua, mub):

    p13.x = p1.x - p3.x;
    p13.y = p1.y - p3.y;
    p13.z = p1.z - p3.z;
    p43.x = p4.x - p3.x;
    p43.y = p4.y - p3.y;
    p43.z = p4.z - p3.z;
    if (abs(p43.x)  < EPS and ABS(p43.y)  < EPS and ABS(p43.z)  < EPS):
        return 0
    p21.x = p2.x - p1.x;
    p21.y = p2.y - p1.y;
    p21.z = p2.z - p1.z;
    if (abs(p21.x)  < EPS and ABS(p21.y)  < EPS and abs(p21.z)  < EPS):
        return 0

    d1343 = p13.x * p43.x + p13.y * p43.y + p13.z * p43.z;
    d4321 = p43.x * p21.x + p43.y * p21.y + p43.z * p21.z;
    d1321 = p13.x * p21.x + p13.y * p21.y + p13.z * p21.z;
    d4343 = p43.x * p43.x + p43.y * p43.y + p43.z * p43.z;
    d2121 = p21.x * p21.x + p21.y * p21.y + p21.z * p21.z;

    denom = d2121 * d4343 - d4321 * d4321;
    if (abs(denom) < EPS):
        return 0
    numer = d1343 * d4321 - d1321 * d4343;

    mua = numer / denom;
    mub = (d1343 + d4321 * (mua)) / d4343;

    pa.x = p1.x + mua * p21.x;
    pa.y = p1.y + mua * p21.y;
    pa.z = p1.z + mua * p21.z;
    pb.x = p3.x + mub * p43.x;
    pb.y = p3.y + mub * p43.y;
    pb.z = p3.z + mub * p43.z;

    return 1

of course, I haven’t tested this

You are really fast, z3r0 d!!

Thank you very much!!

p.s. I’m trying to do a script to subdivide a mesh with more than the 2 of Blender, but it’s getting really hard!! (my poor math doesn’t help much).

Just one more thing (please, don’t get me wrong), with this ,

def LineLineIntersect(p1,p2,p3,p4,pa,pb, mua, mub):

having just the values of p1, p2, p3 and p4, can you give me a light of how to use this function?

Thank you again!! :smiley:

I have absolutely no idea what the function does

and I don’t know how well things will work [python doesn’t have pointers, but objects are passed by refrence, so, are doubles passed by refrence? the code had them passed by pointer, so the behavior might not be the same]

however, the way blender subdivides a quad is pretty simple

the new vert on each of the edges is merely the midpoint of them

and the new vert in the center is merely the midpoint of the two new points on opposite edges [which pair of edges that is shouldn’t matter]

for triangles, there is no vert created in the middle, just the edges are subdivided

[and you can see pretty easy how things are filled simply by trying it, it would take me longer to explain than for you to do]

I understand you, but what i want to do is a script to divide the mesh by 3, 4, or more (i’m interested especialy in the impar numbers 3, 5,…) because it’s impossible in Blender.
It would be easier if all quads were planar, but they’re not, sometimes!!

That function is suposed to find the small line between other 2 lines (or give me 1st and 2nd points equal if the lines intersect).

With the code you give me, it’s easier for me to try to understand the function!!!

I see you know Paul Bourke :slight_smile:

pa, pb, mua and mub are calculated inside the function, you can do 2 things to pass them to the program outside the function,

  • make them global
  • return them explicitely with a return statement at the end of the function.

My try:


from math import abs 
##   Calculate the line segment PaPb that is the shortest route between 
##   two lines P1P2 and P3P4. Calculate also the values of mua and mub where 
##      Pa = P1 + mua (P2 - P1) 
##      Pb = P3 + mub (P4 - P3) 


def LineLineIntersect(p1,p2,p3,p4): 

    var = 0
    p13, p43 = [0,0,0],[0,0,0]
    p21 = [0,0,0]

    p13[0] = p1[0] - p3[0]
    p13[1] = p1[1] - p3[1]
    p13[2] = p1[2] - p3[2]
    p43[0] = p4[0] - p3[0]
    p43[1] = p4[1] - p3[1]; 
    p43[2] = p4[2] - p3[2]; 
    if (abs(p43[0])  < EPS) and (abs(p43[1])  < EPS) and (abs(p43[2])  < EPS): 
        var = 0
    else:
        var = 1
    p21[0] = p2[0] - p1[0]; 
    p21[1] = p2[1] - p1[1]; 
    p21[2] = p2[2] - p1[2]; 
    if (abs(p21[0])  < EPS) and (abs(p21[1])  < EPS) and (abs(p21[2])  < EPS): 
        var = 0 
    else:
        var = 1
    d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2]
    d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2]
    d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2]
    d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2]
    d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2]

    denom = d2121 * d4343 - d4321 * d4321
    if (abs(denom) < EPS)
        var = 0
    else:
        var = 1 
    numer = d1343 * d4321 - d1321 * d4343

    mua = numer / denom
    mub = (d1343 + d4321 * (mua)) / d4343

    pa[0] = p1[0] + mua * p21[0]
    pa[1] = p1[1] + mua * p21[1]
    pa[2] = p1[2] + mua * p21[2]
    pb[0] = p3[0] + mub * p43[0]
    pb[1] = p3[1] + mub * p43[1]
    pb[2] = p3[2] + mub * p43[2]

    return var, pa, pb, mua, mub

If you supply the above function with four vectors it will return var together with pa, pb mua and mub.
From the value of var you can determine if the lines intersect or not, and if they do, pa and pb will be the same point in space.

I didn’t test this, but I’m fairly confident that it works.

On a side note, wouldn’t it be better if you first tried to code it yourself with the help of the info given at the page where you found the c-code?

Greetings,

Wim

Details :
EPS, pa and pb are not defined.
in “mua = numer / denom” denom could be 0.0 and return an error.

import Blender
from Blender  import NMesh
##   Calculate the line segment PaPb that is the shortest route between
##   two lines P1P2 and P3P4. Calculate also the values of mua and mub where
##      Pa = P1 + mua (P2 - P1)
##      Pb = P3 + mub (P4 - P3)


def LineLineIntersect(p1,p2,p3,p4):
    EPS=0.0000001
    var = 0
    p13, p43 = [0,0,0],[0,0,0]
    p21 = [0,0,0]

    p13[0] = p1[0] - p3[0]
    p13[1] = p1[1] - p3[1]
    p13[2] = p1[2] - p3[2]
    p43[0] = p4[0] - p3[0]
    p43[1] = p4[1] - p3[1];
    p43[2] = p4[2] - p3[2];

    if (abs(p43[0])  < EPS) and (abs(p43[1])  < EPS) and (abs(p43[2])  < EPS):
        var = 0
    else:
        var = 1
    p21[0] = p2[0] - p1[0];
    p21[1] = p2[1] - p1[1];
    p21[2] = p2[2] - p1[2];
    if (abs(p21[0])  < EPS) and (abs(p21[1])  < EPS) and (abs(p21[2])  < EPS):
        var = 0
    else:
        var = 1
    d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2]
    d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2]
    d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2]
    d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2]
    d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2]

    denom = d2121 * d4343 - d4321 * d4321
    print denom
    if (abs(denom) < EPS):
        var = 0
    else:
        var = 1
    numer = d1343 * d4321 - d1321 * d4343
    if var==1:
      mua = numer / denom
      mub = (d1343 + d4321 * (mua)) / d4343
      pa=[0.0,0.0,0.0]
      pb=[0.0,0.0,0.0]
       
      pa[0] = p1[0] + mua * p21[0]
      pa[1] = p1[1] + mua * p21[1]
      pa[2] = p1[2] + mua * p21[2]
      pb[0] = p3[0] + mub * p43[0]
      pb[1] = p3[1] + mub * p43[1]
      pb[2] = p3[2] + mub * p43[2]
        
      return [var, pa, pb, mua, mub]
    else:
      return [var]
try:
  O=Blender.Object.GetSelected()[0]
  me=O.getData()
  S=[s for s in me.verts if s.sel==1]
  for s in S: s.sel=0
  print S
  z=len(S)
  print z  
  while z>=4:
        p1=S[z-4]  
        p2=S[z-3]  
        p3=S[z-2]  
        p4=S[z-1]  
        coord=LineLineIntersect(p1,p2,p3,p4)
        print coord 
        f=NMesh.Face()
        for p in [p1,p2]: f.append(me.verts[me.verts.index(p)])               
        f=NMesh.Face()
        for p in [p3,p4]: f.append(me.verts[me.verts.index(p)])               
        me.faces.append(f)
        if coord[0]==1:       
           v=NMesh.Vert()
           for n in [0,1,2] : v[n]=coord[1][n]
           me.verts.append(v)
           v=NMesh.Vert()
           for n in [0,1,2] : v[n]=coord[2][n]
           me.verts.append(v)
           f=NMesh.Face()
           for n in [-1,-2] : f.append(me.verts[n])               
           me.faces.append(f)
           me.update()  
        z-=1
except:
  pass

Thank you, very, very much to all of you!!!

Happy to recover this page !

:slight_smile:

for future reference there is no need to do a

from math import abs

abs is a member of the builtins namespace already.

timmeh

You should look at my script closer : I do not use anything in the math module ! I do not use the math module at all .

i was referring to the other scripts at the start not yours and was only trying to point it out to the others how you dont need the math module for abs

If you test the others scripts you will see that they do not work .