Thought this might be of interest to anyone wanting to use beacons of known location by the angle between them to determine the position of a viewer (robot),
Apologies if I have already posted it before. A good example however of using ChatGPT.
I used ChatGPT to generate the Python and Processing language versions. Amazing how they just worked without tweaking. It failed with a C++ version. Python can be slow for low level programming.
Original FreeBASIC demo.
'=========================================================================
' modified version of this Rosetta code example
''https://rosettacode.org/wiki/Find_the_intersection_of_two_lines#QBasic
'=========================================================================
#Define NaN 0 / 0 ' FreeBASIC returns -1.#IND
'some useful defines
Const Pi = 4 * Atn(1)
Dim Shared As single TwoPi = 8 * Atn(1)
Dim Shared As single RtoD = 180 / Pi ' radians * RtoD = degrees
Dim Shared As single DtoR = Pi / 180 ' degrees * DtoR = radians
screenres 800,600,32
dim as integer mx,my,mb
dim as single x1,y1,x2,y2,x3,y3,x4,y4,a1,a2
'positions of two beacons
x1 = 150
y1 = 150
x2 = 500
y2 = 300
do
getmouse mx,my,,mb
screenlock
cls
locate 2,2
a1 = atan2(my-y1,mx-x1)*RtoD
a2 = atan2(my-y2,mx-x2)*RtoD
if a1<0 then a1 = a1 + 360
if a2<0 then a2 = a2 + 360
circle (x1,y1),2,rgb(255,0,0),,,,f
circle (x1,y1),5,rgb(255,0,0)
draw string (x1+5,y1),"A1 = (" & x1 & ","& y1 & ") angle =" & a1 'int(a1)
circle (x2,y2),2,rgb(255,255,0),,,,f
circle (x2,y2),5,rgb(255,255,0)
draw string (x2+5,y2),"A2 = (" & x2 & ","& y2 & ") angle =" & a2 'int(a2)
circle (mx,my),2,rgb(0,0,255),,,,f
circle (mx,my),5,rgb(100,100,255)
x3 = x1+Cos(a1*DtoR)
y3 = y1+Sin(a1*DtoR)
x2 = x2
x4 = x2+Cos(a2*DtoR)
y2 = y2
y4 = y2+Sin(a2*DtoR)
Dim As single a1 = y3 - y1
Dim As single b1 = x1 - x3
Dim As single c1 = a1 * x1 + b1 * y1
Dim As single a2 = y4 - y2
Dim As single b2 = x2 - x4
Dim As single c2 = a2 * x2 + b2 * y2
Dim As single det = a1 * b2 - a2 * b1
x3 = (b2 * c1 - b1 * c2) / det
y3 = (a1 * c2 - a2 * c1) / det
circle (x3, y3),8,rgb(200,0,200)
line (x3,y3)-(x1,y1),rgb(255,0,0)
line (x3,y3)-(x2,y2),rgb(0,255,0)
locate 4,2
print "mx =";mx;" my =";my
print
'print " x3 =";int(x3+0.5);" y3 =";int(y3+0.5)
print " x3 =";(x3+0.5);" y3 =";(y3+0.5)
screenunlock
sleep 2
loop until multikey(&H01)
ChatGPT translation to Python language:
import pygame
import math
import sys
import time
# Initialize Pygame
pygame.init()
# Screen setup
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Beacon Positioning")
clock = pygame.time.Clock()
# Useful constants
Pi = math.atan(1) * 4
TwoPi = 8 * math.atan(1)
RtoD = 180 / Pi # radians to degrees
DtoR = Pi / 180 # degrees to radians
# Beacon positions
x1, y1 = 150, 150
x2, y2 = 500, 300
def draw_text(surface, text, position, color=(255,255,255)):
font = pygame.font.SysFont(None, 24)
text_surface = font.render(text, True, color)
surface.blit(text_surface, position)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Get mouse position
mx, my = pygame.mouse.get_pos()
# Calculate angles from beacons to mouse
a1 = math.atan2(my - y1, mx - x1) * RtoD
a2 = math.atan2(my - y2, mx - x2) * RtoD
if a1 < 0:
a1 += 360
if a2 < 0:
a2 += 360
# Clear screen
screen.fill((0, 0, 0))
# Draw beacons
pygame.draw.circle(screen, (255, 0, 0), (x1, y1), 5)
pygame.draw.circle(screen, (255, 0, 0), (x1, y1), 2)
draw_text(screen, f"A1 = ({x1},{y1}) angle={a1:.2f}", (x1 + 5, y1))
pygame.draw.circle(screen, (255, 255, 0), (x2, y2), 5)
pygame.draw.circle(screen, (255, 255, 0), (x2, y2), 2)
draw_text(screen, f"A2 = ({x2},{y2}) angle={a2:.2f}", (x2 + 5, y2))
# Draw mouse position
pygame.draw.circle(screen, (0, 0, 255), (mx, my), 5)
pygame.draw.circle(screen, (100, 100, 255), (mx, my), 2)
# Compute points for the lines based on angles
x3 = x1 + math.cos(a1 * DtoR)
y3 = y1 + math.sin(a1 * DtoR)
x4 = x2 + math.cos(a2 * DtoR)
y4 = y2 + math.sin(a2 * DtoR)
# Line equations coefficients
a1_coef = y3 - y1
b1_coef = x1 - x3
c1 = a1_coef * x1 + b1_coef * y1
a2_coef = y4 - y2
b2_coef = x2 - x4
c2 = a2_coef * x2 + b2_coef * y2
# Determinant
det = a1_coef * b2_coef - a2_coef * b1_coef
if det != 0:
# Intersection point
xi = (b2_coef * c1 - b1_coef * c2) / det
yi = (a1_coef * c2 - a2_coef * c1) / det
# Draw the intersection point
pygame.draw.circle(screen, (200, 0, 200), (int(xi), int(yi)), 8)
# Draw lines from intersection to beacons
pygame.draw.line(screen, (255, 0, 0), (xi, yi), (x1, y1))
pygame.draw.line(screen, (0, 255, 0), (xi, yi), (x2, y2))
# Display mouse coordinates
draw_text(screen, f"mx = {mx} my = {my}", (10, 10))
# Display intersection point
draw_text(screen, f"x3 = {xi:.2f} y3 = {yi:.2f}", (10, 40))
else:
# Lines are parallel; no intersection
draw_text(screen, "Lines are parallel, no intersection.", (10, 40))
draw_text(screen, f"mx = {mx} my = {my}", (10, 10))
pygame.display.flip()
# Delay for 2 seconds
time.sleep(2)
pygame.quit()
sys.exit()
ChatGPT translation to Processing language:
// Define constants
final float Pi = 4 * atan(1);
final float TwoPi = 8 * atan(1);
final float RtoD = 180.0 / Pi; // Radians to Degrees
final float DtoR = Pi / 180.0; // Degrees to Radians
// Beacon positions
float x1 = 150;
float y1 = 150;
float x2 = 500;
float y2 = 300;
void setup() {
size(800, 600);
frameRate(30);
noStroke();
textSize(12);
}
void draw() {
background(255);
// Get mouse position
float mx = mouseX;
float my = mouseY;
int mb = mouseButton; // Not used directly here, but for completeness
// Calculate angles from beacons to mouse
float a1 = atan2(my - y1, mx - x1) * RtoD;
float a2 = atan2(my - y2, mx - x2) * RtoD;
if (a1 < 0) a1 += 360;
if (a2 < 0) a2 += 360;
// Draw beacon 1
fill(255, 0, 0);
ellipse(x1, y1, 10, 10);
fill(0);
text("A1 = (" + int(x1) + "," + int(y1) + ") angle = " + nf(a1, 0, 2), x1 + 5, y1);
// Draw beacon 2
fill(255, 255, 0);
ellipse(x2, y2, 10, 10);
fill(0);
text("A2 = (" + int(x2) + "," + int(y2) + ") angle = " + nf(a2, 0, 2), x2 + 5, y2);
// Draw mouse position
fill(0, 0, 255);
ellipse(mx, my, 10, 10);
fill(100, 100, 255);
ellipse(mx, my, 20, 20);
// Calculate points based on angles
float x3 = x1 + cos(a1 * DtoR);
float y3 = y1 + sin(a1 * DtoR);
float x4 = x2 + cos(a2 * DtoR);
float y4 = y2 + sin(a2 * DtoR);
// Line-line intersection calculation
float a1_coef = y3 - y1;
float b1_coef = x1 - x3;
float c1 = a1_coef * x1 + b1_coef * y1;
float a2_coef = y4 - y2;
float b2_coef = x2 - x4;
float c2 = a2_coef * x2 + b2_coef * y2;
float det = a1_coef * b2_coef - a2_coef * b1_coef;
float xi = 0;
float yi = 0;
if (abs(det) > 0.0001) { // Prevent division by zero
xi = (b2_coef * c1 - b1_coef * c2) / det;
yi = (a1_coef * c2 - a2_coef * c1) / det;
}
// Draw intersection point
fill(200, 0, 200);
ellipse(xi, yi, 16, 16);
// Draw lines from intersection to beacons
stroke(255, 0, 0);
line(xi, yi, x1, y1);
stroke(0, 255, 0);
line(xi, yi, x2, y2);
noStroke();
// Display coordinates
fill(0);
text("mx = " + int(mx) + " my = " + int(my), 10, 20);
text("x3 = " + nf(xi, 0, 2) + " y3 = " + nf(yi, 0, 2), 10, 40);
// Optional: Delay similar to sleep 2 in FreeBASIC
// In Processing, the frame rate controls update speed.
// To mimic a delay, you could use delay(2000); but it's usually unnecessary here.
}
I assumed Python was just slow but then noticed the line at the end with 2 second delay.
# Delay for 2 seconds
time.sleep(2)
If you comment out or delete that line the code will run much faster!!
The sleep 2 in FreeBASIC is required for reasons I don't know something to do with freeing up the cpu otherwise the code will become very erratic with big pauses.