AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting Help (https://forums.alliedmods.net/forumdisplay.php?f=11)
-   -   Solved Line僕ine intersection (https://forums.alliedmods.net/showthread.php?t=317199)

CrazY. 07-02-2019 14:21

Line僕ine intersection
 
Hello, supposing I've two lines, A and B, both with start and end position (axis), how could I check if the lines intersect?

Natsheh 07-03-2019 06:34

Re: Line僕ine intersection
 
Check this out I wrote it on phone and didn't test tell me if it has any bug, basically it will return bitsum value depends on the intersection in each axis and it also return the intersection point.

PHP Code:


#define X_AXIS 0
#define Y_AXIS 1
#define Z_AXIS 2

#define VECTORS_DONT_INTERSECT 0
#define VECTORS_INTERSECT_XY (1<<0)
#define VECTORS_INTERSECT_YZ (1<<1)
#define VECTORS_INTERSECT_ZX (1<<2)
#define VECTORS_INTERSECT_3D (1<<0)|(1<<1)|(1<<2)

new const iaDimensions[ ][ ] = {
     { 
X_AXISY_AXIS },
     { 
Y_AXISZ_AXIS },
     { 
Z_AXISX_AXIS }
}

DoesVectorsIntersect(const Float:fV1Init[3], const Float:fV1Final[3], const Float:fV2Init[3], const Float:fV2Final[3], Float:tolerance=1.0Float:fPoint[3])
{
    new 
Float:fFactorV1[3], Float:fFactorV2[3], g_return;
    
    for(new 
Float:XFloat:YV1Float:YV2Float:fDis_xv[2], Float:fDis_yv[2], i3i++)
    {
          
fDis_xv[0] = (fV1Final[iaDimensions[i][0]] - fV1Init[iaDimensions[i][0]]);
          
fDis_xv[1] = (fV2Final[iaDimensions[i][0]] - fV2Init[iaDimensions[i][0]]);
          
fDis_yv[0] = (fV1Final[iaDimensions[i][1]] - fV1Init[iaDimensions[i][1]]);
          
fDis_yv[1] = (fV2Final[iaDimensions[i][1]] - fV2Init[iaDimensions[i][1]])

          if(
fDis_xv[0] != 0.0fFactorV1[i] = fDis_yv[0] / fDis_xv[0];
          if(
fDis_xv[1] != 0.0fFactorV2[i] = fDis_yv[1] / fDis_xv[1];
          
          if( (
fDis_yv[0] == 0.0 && fDis_yv[1] == 0.0) || (!fDis_xv[0] && !fDis_xv[1]) || (fFactorV1[i] == fFactorV2[i] && fFactorV1[i] != 0.0) ) continue;

          if((
fFactorV1[i] == fFactorV2[i] && fFactorV1[i] != 0.0)) = ((fV1Init[iaDimensions[i][0]] * fFactorV1[i]) - (fV2Init[iaDimensions[i][0]] *  fFactorV2[i]) + fV2Init[iaDimensions[i][1]] - fV1Init[iaDimensions[i][1]]) / (fFactorV1[i] - fFactorV2[i]);
          else 
fV1Final[iaDimensions[i][0]];
          
YV1 = (fFactorV1[i] * ( fV1Init[iaDimensions[i][0]] ) + fV1Init[iaDimensions[i][1]]);
          
YV2 = (fFactorV2[i] * ( fV2Init[iaDimensions[i][0]] ) + fV2Init[iaDimensions[i][1]]);

          if( 
YV1 == YV2 || ((YV1 tolerance) <= YV2 <= (YV1 tolerance)) || ((YV2 tolerance) <= YV1 <= (YV2 tolerance)) )
           {
                   
fPoint[iaDimensions[i][0]] = X;
                   switch( 
)
                   {
                          case 
0g_return |= VECTORS_INTERSECT_XY;
                          case 
1g_return |= VECTORS_INTERSECT_YZ;
                          case 
2g_return |= VECTORS_INTERSECT_ZX;
                   }
           }

           
    }
    return 
g_return;



CrazY. 07-03-2019 14:21

Re: Line僕ine intersection
 
I did some tests, doesn't work. The code doesn't identifies the intersect and sometimes return true when the lines are not intersect.

Natsheh 07-03-2019 14:24

Re: Line僕ine intersection
 
Can you show your testing code and the outputs?


BTW if You noticed the function doesn't return true it returns bitsum values

CrazY. 07-03-2019 14:31

Re: Line僕ine intersection
 
Sure. Red laser is the first line, blue is the second line. As you can see, the lines aren't intersected but the code is returning true.

https://i.imgur.com/1jsPjGS.png


PHP Code:

#include <amxmodx>
#include <beams>
#include <engine>
#include <xs>

new const SPR_LASERBEAM[] = "sprites/laserbeam.spr";

enum
{
    
pitch// x
    
yaw// y
    
roll // z
};

enum (<<= 1)
{
    
INTERSECT_YX 1,
    
INTERSECT_XZ,
    
INTERSECT_ZY,
};

const 
INTERSECT_NONE 0;
const 
INTERSECT_YX = (1<<0);
const 
INTERSECT_XZ = (1<<1);
const 
INTERSECT_ZY = (1<<2);
const 
INTERSECT_3D = (INTERSECT_YX INTERSECT_XZ INTERSECT_ZY);

new const 
DIMENSIONS[][] = 
{
    { 
yawpitch },
    { 
rollyaw },
    { 
pitchroll }
};

new 
g_beam1g_beam2;

public 
plugin_init()
{
    
register_plugin("env_beam""1.0""CrazY.");
    
register_clcmd("say /beam""cmd_beam");

    
g_beam1 Beam_Create(SPR_LASERBEAM10.0);
    
Beam_SetColor(g_beam1Float:{150.00.00.0});
    
Beam_SetFrame(g_beam110.0);
    
Beam_SetScrollRate(g_beam1255.0);
    
Beam_SetBrightness(g_beam1200.0);
    
Beam_SetType(g_beam1BEAM_POINTS);

    
g_beam2 Beam_Create(SPR_LASERBEAM10.0);
    
Beam_SetColor(g_beam2Float:{0.00.0150.0});
    
Beam_SetFrame(g_beam210.0);
    
Beam_SetScrollRate(g_beam2255.0);
    
Beam_SetBrightness(g_beam2200.0);
    
Beam_SetType(g_beam2BEAM_POINTS);

    
set_task(1.0"task_beam", .flags="b");
}

public 
plugin_precache()
{
    
precache_model(SPR_LASERBEAM);
}

public 
cmd_beam(id)
{
    
show_menu_beam(id);
    return 
PLUGIN_HANDLED;
}

show_menu_beam(id)
{
    new 
menu menu_create("env_beam""menu_beam");

    
menu_additem(menu"Set start pos (beam1)");
    
menu_additem(menu"Set end pos (beam1)^n");
    
menu_additem(menu"Set start pos (beam2)");
    
menu_additem(menu"Set end pos (beam2)");

    
menu_display(idmenu);
}

public 
menu_beam(idmenuitem)
{
    
menu_destroy(menu);

    new 
Float:origin[3];
    
entity_get_vector(idEV_VEC_originorigin);
    
    switch (
item)
    {
        case 
0:
        {
            
Beam_SetStartPos(g_beam1origin);
            
Beam_RelinkBeam(g_beam1);
            
show_menu_beam(id);
        }
        case 
1:
        {
            
Beam_SetEndPos(g_beam1origin);
            
Beam_RelinkBeam(g_beam1);
            
show_menu_beam(id);
        }
        case 
2:
        {
            
Beam_SetStartPos(g_beam2origin);
            
Beam_RelinkBeam(g_beam2);
            
show_menu_beam(id);
        }
        case 
3:
        {
            
Beam_SetEndPos(g_beam2origin);
            
Beam_RelinkBeam(g_beam2);
            
show_menu_beam(id);
        }
    }

    return 
PLUGIN_HANDLED;
}

public 
task_beam()
{
    new 
Float:b1_start_pos[3], Float:b1_end_pos[3];
    new 
Float:b2_start_pos[3], Float:b2_end_pos[3];

    
Beam_GetStartPos(g_beam1b1_start_pos);
    
Beam_GetEndPos(g_beam1b1_end_pos);

    
Beam_GetStartPos(g_beam2b2_start_pos);
    
Beam_GetEndPos(g_beam2b2_end_pos);

    if (
DoesVectorsIntersect(b1_start_posb1_end_posb2_start_posb2_end_pos) & INTERSECT_3D)
        
client_print(0print_center"intersect = TRUE");
    else
        
client_print(0print_center"intersect = FALSE");
}

DoesVectorsIntersect(const Float:fV1Init[3], const Float:fV1Final[3], const Float:fV2Init[3], const Float:fV2Final[3], Float:fPoint[3] = {0.00.00.0})
{
    new 
Float:fFactorV1[3], Float:fFactorV2[3], g_return;
    
    for(new 
Float:Xi3i++)
    {
          
fFactorV1[i] = (fV1Final[DIMENSIONS[i][0]] - fV1Init[DIMENSIONS[i][0]]) / (fV1Final[DIMENSIONS[i][1]] - fV1Init[DIMENSIONS[i][1]]);
          
fFactorV2[i] = (fV2Final[DIMENSIONS[i][0]] - fV2Init[DIMENSIONS[i][0]]) / (fV2Final[DIMENSIONS[i][1]] - fV2Init[DIMENSIONS[i][1]]);
          
          
= ((fV2Final[DIMENSIONS[i][0]] - fV1Final[DIMENSIONS[i][0]]) + (fFactorV2[i] * fV2Final[DIMENSIONS[i][1]]) - (fFactorV1[i] * fV1Final[DIMENSIONS[i][1]])) / (fFactorV2[i] - fFactorV1[i]);
          if(((
fFactorV1[i] * (fV1Final[DIMENSIONS[i][1]] - X) + fV1Final[DIMENSIONS[i][0]])) == (fFactorV2[i] * (fV2Final[DIMENSIONS[i][1]] - X) + fV2Final[DIMENSIONS[i][0]]))
           {
                   
fPoint[DIMENSIONS[i][1]] = X;
                   switch( 
)
                   {
                          case 
0g_return |= INTERSECT_YX;
                          case 
2g_return |= INTERSECT_XZ;
                          case 
1g_return |= INTERSECT_ZY;
                   }
           }

           
    }
    return 
g_return;
}

/*public static bool ClosestPointsOnTwoLines(out Vector3 closestPointLine1, out Vector3 closestPointLine2, Vector3 linePoint1, Vector3 lineVec1, Vector3 linePoint2, Vector3 lineVec2){
 
        closestPointLine1 = Vector3.zero;
        closestPointLine2 = Vector3.zero;
 
        float a = Vector3.Dot(lineVec1, lineVec1);
        float b = Vector3.Dot(lineVec1, lineVec2);
        float e = Vector3.Dot(lineVec2, lineVec2);
 
        float d = a*e - b*b;
 
        //lines are not parallel
        if(d != 0.0f){
 
            Vector3 r = linePoint1 - linePoint2;
            float c = Vector3.Dot(lineVec1, r);
            float f = Vector3.Dot(lineVec2, r);
 
            float s = (b*f - c*e) / d;
            float t = (a*f - c*b) / d;
 
            closestPointLine1 = linePoint1 + lineVec1 * s;
            closestPointLine2 = linePoint2 + lineVec2 * t;
 
            return true;
        }
 
        else{
            return false;
        }
    }    */

/*intersection(Float:vec1_start[3], Float:vec1_end[3], Float:vec2_start[3], Float:vec2_end[3])
{
    new Float:factorA[3], Float:factorB[3], ret, Float:num;

    for (new axis = 0; axis < 3; axis++)
    {
        factorA[axis] = (vec1_end[DIMENSIONS[axis][0]] - vec1_start[DIMENSIONS[axis][0]]) / (vec1_end[DIMENSIONS[axis][1]] - vec1_start[DIMENSIONS[axis][1]]);
        factorB[axis] = (vec2_end[DIMENSIONS[axis][0]] - vec2_start[DIMENSIONS[axis][0]]) / (vec2_end[DIMENSIONS[axis][1]] - vec2_start[DIMENSIONS[axis][1]]);
        num = ((vec2_end[DIMENSIONS[axis][0]] - vec1_end[DIMENSIONS[axis][0]]) + (factorB[axis] * vec2_end[DIMENSIONS[axis][1]]) - (factorA[axis] * vec1_end[DIMENSIONS[axis][1]])) / (factorB[axis] - factorA[axis]);
    
        if (((factorA[axis] * (vec1_end[DIMENSIONS[axis][1]] - num) + vec1_end[DIMENSIONS[axis][0]])) == ((factorB[axis] * (vec2_end[DIMENSIONS[axis][1]] - num) + vec2_end[DIMENSIONS[axis][0]])))
        {
            switch (axis)
            {
                case pitch: ret |= INTERSECT_YX;
                case yaw: ret |= INTERSECT_XZ;
                case roll: ret |= INTERSECT_ZY;
            }
        }
    }

    return ret;
}*/

/*DoesVectorsIntersect(const Float:fV1Init[3], const Float:fV1Final[3], const Float:fV2Init[3], const Float:fV2Final[3], Float:fPoint[3])
{
    new Float:fFactorV1[3], Float:fFactorV2[3], g_return;
    
    for(new Float:X, i; i < 3; i++)
    {
          fFactorV1[i] = (fV1Final[iaDimensions[i][0]] - fV1Init[iaDimensions[i][0]]) / (fV1Final[iaDimensions[i][1]] - fV1Init[iaDimensions[i][1]]);
          fFactorV2[i] = (fV2Final[iaDimensions[i][0]] - fV2Init[iaDimensions[i][0]]) / (fV2Final[iaDimensions[i][1]] - fV2Init[iaDimensions[i][1]]);
          
          X = ((fV2Final[iaDimensions[i][0]] - fV1Final[iaDimensions[i][0]]) + (fFactorV2[i] * fV2Final[iaDimensions[i][1]]) - (fFactorV1[i] * fV1Final[iaDimensions[i][1]])) / (fFactorV2[i] - fFactorV1[i]);
          if(((fFactorV1[i] * (fV1Final[iaDimensions[i][1]] - X) + fV1Final[iaDimensions[i][0]])) == (fFactorV2[i] * (fV2Final[iaDimensions[i][1]] - X) + fV2Final[iaDimensions[i][0]]))
           {
                   fPoint[iaDimensions[i][1]] = X;
                   switch( i )
                   {
                          case 0: g_return |= VECTORS_INTERSECT_YX;
                          case 2: g_return |= VECTORS_INTERSECT_XZ;
                          case 1: g_return |= VECTORS_INTERSECT_ZY;
                   }
           }

           
    }
    return g_return;
}*/ 

Quote:

BTW if You noticed the function doesn't return true it returns bitsum values
Yea, true I meant VECTORS_INTERSECT_3D.

Natsheh 07-03-2019 14:59

Re: Line僕ine intersection
 
Do this to check all of them are intersecting

if (DoesVectorsIntersect(b1_start_pos, b1_end_pos, b2_start_pos, b2_end_pos) == INTERSECT_3D)

CrazY. 07-03-2019 15:02

Re: Line僕ine intersection
 
now it only returns false.

Natsheh 07-03-2019 15:05

Re: Line僕ine intersection
 
Can you provide me with log debug output?

Both v start and end pos.
And the function returns

fysiks 07-03-2019 22:37

Re: Line僕ine intersection
 
One thing to remember is that checking for equality of two floating-point numbers will almost always return false (the values will very likely never been exactly the same). You would need to add a tolerance to calculate "how close is close enough".

Natsheh 07-04-2019 05:16

Re: Line僕ine intersection
 
I think you got a point or I should do floatround?

Code updated.


All times are GMT -4. The time now is 06:19.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.