Skip to content

Commit 289b65c

Browse files
committed
closest point on a line
1 parent 9d531eb commit 289b65c

File tree

3 files changed

+136
-0
lines changed

3 files changed

+136
-0
lines changed

closest_point_on_line/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Closest Point On Line
2+
An example of using dot product to find a point on a line closest to another point (line projection)
3+
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/**********************************************************************************************
2+
*
3+
* raylib-extras, closest point on a line to another point
4+
*
5+
* LICENSE: MIT
6+
*
7+
* Copyright (c) 2024 Jeffery Myers
8+
*
9+
* Permission is hereby granted, free of charge, to any person obtaining a copy
10+
* of this software and associated documentation files (the "Software"), to deal
11+
* in the Software without restriction, including without limitation the rights
12+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
* copies of the Software, and to permit persons to whom the Software is
14+
* furnished to do so, subject to the following conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be included in all
17+
* copies or substantial portions of the Software.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25+
* SOFTWARE.
26+
*
27+
**********************************************************************************************/
28+
29+
#include "raylib.h"
30+
#include "raymath.h"
31+
32+
33+
// the line we want to test against
34+
Vector2 LineSP = { 100 , 100 };
35+
Vector2 LineEP = { 500 , 500 };
36+
37+
// the point that is on the line that is closest to the mouse
38+
Vector2 NearestPoint = { 0 };
39+
40+
// is the nearest point actualy on the line, or outside it's SP/EP
41+
bool OnLine = false;
42+
43+
void GameInit()
44+
{
45+
LineEP.x = GetScreenWidth() - LineSP.x;
46+
LineEP.y = GetScreenHeight() - LineSP.y;
47+
}
48+
49+
bool GameUpdate()
50+
{
51+
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
52+
{
53+
LineSP = GetMousePosition();
54+
}
55+
56+
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT))
57+
{
58+
LineEP = GetMousePosition();
59+
}
60+
else
61+
{
62+
// compute the vector for the line
63+
Vector2 lineVec = Vector2Subtract(LineEP, LineSP);
64+
65+
// see how long the line is
66+
float magnatude = Vector2Length(lineVec);
67+
68+
// normalize the vector so it's just a direction
69+
lineVec = Vector2Normalize(lineVec);
70+
71+
// compute the vector from a point on the line to the mouse
72+
Vector2 vecToMouse = Vector2Subtract(GetMousePosition(), LineSP);
73+
74+
// the dot product is the distance along the vector from the point to the 'leg' of the triangle made
75+
// between the vector to the mouse and the vector of the line, thus this is the distance from
76+
// the start point to the nearest point on the line to the mouse
77+
float dot = Vector2DotProduct(vecToMouse, lineVec);
78+
79+
// compute the actual point relative to the start point
80+
NearestPoint = Vector2Add(LineSP, Vector2Scale(lineVec, dot));
81+
82+
// if the distance is less than 0, then the nearest point is behind the start point
83+
// if the distance is larger than the line length, then it's off the end
84+
OnLine = dot >= 0 && dot <= magnatude;
85+
}
86+
87+
return true;
88+
}
89+
90+
void Draw2D()
91+
{
92+
// draw our line
93+
DrawLineV(LineSP, LineEP, WHITE);
94+
95+
// draw the nearest point if we are not dragging a line
96+
if (!IsMouseButtonDown(MOUSE_BUTTON_LEFT))
97+
DrawCircleV(NearestPoint, 10, OnLine ? YELLOW : RED);
98+
99+
DrawText("Drag to draw new line", 0, 0, 20, WHITE);
100+
}
101+
102+
void GameDraw()
103+
{
104+
BeginDrawing();
105+
ClearBackground(DARKGRAY);
106+
Draw2D();
107+
DrawFPS(0, GetScreenHeight() - 20);
108+
EndDrawing();
109+
}
110+
111+
int main()
112+
{
113+
SetConfigFlags(FLAG_VSYNC_HINT | FLAG_WINDOW_RESIZABLE);
114+
InitWindow(1280, 800, "Point on line nearest another point");
115+
SetTargetFPS(300);
116+
117+
GameInit();
118+
119+
while (!WindowShouldClose())
120+
{
121+
if (!GameUpdate())
122+
break;
123+
124+
GameDraw();
125+
}
126+
127+
CloseWindow();
128+
return 0;
129+
}

closest_point_on_line/premake5.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
baseName = path.getbasename(os.getcwd())
3+
4+
defineWorkspace(baseName)

0 commit comments

Comments
 (0)