This question already has answers here:
How to rotate a square around x-axis in a 3D space
(1 answer)
Pygame rotating cubes around axis
(1 answer)
Closed 1 year ago.
I want to project a 3d point onto a 2d plane (screen).
Here is my code as well as the class that converts 3d coordinate to 2d coordinate.
The class to convert 3d coordinate to 2d coordinate:
class dtod(pygame.sprite.Sprite):
def __init__(self, point, scale):
super().__init__()
self.point = numpy.array(point)
width, height = pygame.display.get_surface().get_size()
self.angle = 0
self.point[0] = (self.point[0] * 1) / self.point[2]
self.point[1] = (self.point[1] * 1) / self.point[2]
self.projection = numpy.array(
[[math.cos(self.angle), math.sin(self.angle), 0.], [math.sin(self.angle), math.cos(self.angle), 0.]])
self.point = numpy.dot(self.projection, self.point)
self.point = ((self.point[0] * scale) + width / 2, height / 2 - (self.point[1] * scale))
The main code where I draw the things:
import pygame
import numpy as np
from coord import dtod
import math
pygame.init()
screen = pygame.display.set_mode((0, 0))
run = True
width, height = screen.get_size()
colors = {"white": (255, 255, 255), "red": (255, 0, 0), "green": (150, 253, 55), "blue": (0,
227, 227), "orange": (255, 127, 39), "grey": (64, 64, 64), "yellow": (255, 240, 0)}
tx, ty, tz = 0., 0., 0.
fps = pygame.time.Clock()
def cos(x):
return math.cos(x)
def sin(x):
return math.sin(x)
rx = np.array([[1., 0., 0.], [0., cos(tx), -sin(tx)], [0., sin(tx), cos(tx)]])
ry = np.array([[cos(ty), 0., sin(ty)], [0., 1., 0.], [-sin(ty), 0., cos(ty)]])
rz = np.array([[cos(tz), -sin(ty), 0.], [sin(ty), cos(ty), 0.], [0., 0., 1.]])
scale = 200
p1 = np.array([0.5, 0.5, 1.])
p2 = np.array([-0.5, 0.5, 1.])
p3 = np.array([-0.5, -0.5, 1.])
p4 = np.array([0.5, -0.5, 1.])
p5 = np.array([0.5, 0.5, -2.])
p6 = np.array([-0.5, 0.5, -2.])
p7 = np.array([-0.5, -0.5, -2.])
p8 = np.array([0.5, -0.5, -2.])
def transform(tx, ty, tz):
global rx, ry, rz, p1, p2, p3, p4, p5, p6, p7, p8
rx = np.array([[1., 0., 0.], [0., cos(tx), -sin(tx)], [0., sin(tx), cos(tx)]])
ry = np.array([[cos(ty), 0., sin(ty)], [0., 1., 0.], [-sin(ty), 0., cos(ty)]])
rz = np.array([[cos(tz), -sin(ty), 0.], [sin(ty), cos(ty), 0.], [0., 0., 1.]])
p1 = np.dot(rx, p1)
p1 = np.dot(ry, p1)
p1 = np.dot(rz, p1)
p2 = np.dot(rx, p2)
p2 = np.dot(ry, p2)
p2 = np.dot(rz, p2)
p3 = np.dot(rx, p3)
p3 = np.dot(ry, p3)
p3 = np.dot(rz, p3)
p4 = np.dot(rx, p4)
p4 = np.dot(ry, p4)
p4 = np.dot(rz, p4)
p5 = np.dot(rx, p5)
p5 = np.dot(ry, p5)
p5 = np.dot(rz, p5)
p6 = np.dot(rx, p6)
p6 = np.dot(ry, p6)
p6 = np.dot(rz, p6)
p7 = np.dot(rx, p7)
p7 = np.dot(ry, p7)
p7 = np.dot(rz, p7)
p8 = np.dot(rx, p8)
p8 = np.dot(ry, p8)
p8 = np.dot(rz, p8)
while run:
screen.fill((0, 0, 0))
fps.tick(60)
transform(tx, ty, tz)
pygame.draw.circle(screen, colors["white"], dtod(p1, scale).point, 5)
pygame.draw.circle(screen, colors["white"], dtod(p2, scale).point, 5)
pygame.draw.circle(screen, colors["white"], dtod(p3, scale).point, 5)
pygame.draw.circle(screen, colors["white"], dtod(p4, scale).point, 5)
pygame.draw.circle(screen, colors["white"], dtod(p5, scale).point, 5)
pygame.draw.circle(screen, colors["white"], dtod(p6, scale).point, 5)
pygame.draw.circle(screen, colors["white"], dtod(p7, scale).point, 5)
pygame.draw.circle(screen, colors["white"], dtod(p8, scale).point, 5)
pygame.draw.line(screen, colors["white"], dtod(p1, scale).point, dtod(p2, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p2, scale).point, dtod(p3, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p3, scale).point, dtod(p4, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p4, scale).point, dtod(p1, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p5, scale).point, dtod(p6, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p6, scale).point, dtod(p7, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p7, scale).point, dtod(p8, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p8, scale).point, dtod(p5, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p1, scale).point, dtod(p5, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p6, scale).point, dtod(p2, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p7, scale).point, dtod(p3, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p8, scale).point, dtod(p4, scale).point)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
run = False
pygame.display.update()
pygame.quit()
The logic I used:
I m using orthographic projection technique, and to get a feel of perception, I m dividing the x and y coordinates by depth (z-component) before actually converting 3d->2d.
Thank you in advance
Finally I made that, oh my god I am so happy.
Use the following code, it works fine.
The class to convert 3d-coordinates -> 2d-coordinates:
class dtod(pygame.sprite.Sprite):
def __init__(self, point, scale):
super().__init__()
self.point = numpy.array(point)
width, height = pygame.display.get_surface().get_size()
self.angle = 2 * math.pi / 3
self.length = 5
self.projection = numpy.array(
[[(self.length / math.tan(self.angle)) / (self.point[2] - (self.length / math.tan(self.angle))), 0., 0.],
[0., (self.length / math.tan(self.angle)) / (self.point[2] - (self.length / math.tan(self.angle))), 0.]])
self.point = numpy.dot(self.projection, self.point)
self.point = ((self.point[0] * scale) + width / 2, height / 2 - (self.point[1] * scale))
The main code where I draw the cube:
import pygame
import numpy as np
from coord import dtod
import math
pygame.init()
screen = pygame.display.set_mode((0, 0))
run = True
width, height = screen.get_size()
colors = {"white": (255, 255, 255), "red": (255, 0, 0), "green": (150,253,55),"blue": (0, 227, 227),
"orange": (255, 127, 39),
"grey": (64, 64, 64), "yellow": (255, 240, 0)}
tx, ty, tz = 0., 0., 0.
fps = pygame.time.Clock()
x, y, z = 0, 0, 0
def cos(x):
return math.cos(x)
def sin(x):
return math.sin(x)
rotation_matrices = [np.array([[1., 0., 0.], [0., cos(tx), -sin(tx)], [0.,
sin(tx), cos(tx)]]), np.array([[cos(ty), 0., sin(ty)], [0., 1., 0.], [-sin(ty),
0., cos(ty)]]), np.array([[cos(tz), -sin(ty), 0.], [sin(ty), cos(ty), 0.], [0.,
0., 1.]])]
scale = 200
points = [np.array([0.5, 0.5, 0.5]), np.array([-0.5, 0.5, 0.5]), np.array([-0.5,
-0.5, 0.5]),
np.array([0.5, -0.5, 0.5]), np.array([0.5, 0.5, -0.5]),
np.array([-0.5, 0.5, -0.5]),
np.array([-0.5, -0.5, -0.5]), np.array([0.5, -0.5, -0.5])]
def transform(tx, ty, tz):
global points, rotation_matrices
rotation_matrices = [np.array([[1., 0., 0.], [0., cos(tx), -sin(tx)], [0.,
sin(tx), cos(tx)]]),
np.array([[cos(ty), 0., sin(ty)], [0., 1., 0.], [-
sin(ty), 0., cos(ty)]]),
np.array([[cos(tz), -sin(tz), 0.], [sin(tz), cos(tz),
0.], [0., 0., 1.]])]
for i in range(8):
for j in range(3):
points[i] = np.dot(rotation_matrices[j], points[i])
while run:
screen.fill((0, 0, 0))
fps.tick(60)
transform(tx, ty, tz)
for i in range(8):
pygame.draw.circle(screen, colors["white"], dtod(points[i],
scale).point, 5)
pygame.draw.line(screen, colors["white"], dtod(points[0], scale).point,
dtod(points[1], scale).point)
pygame.draw.line(screen, colors["white"], dtod(points[1], scale).point,
dtod(points[2], scale).point)
pygame.draw.line(screen, colors["white"], dtod(points[2], scale).point,
dtod(points[3], scale).point)
pygame.draw.line(screen, colors["white"], dtod(points[3], scale).point,
dtod(points[0], scale).point)
pygame.draw.line(screen, colors["white"], dtod(points[4], scale).point,
dtod(points[5], scale).point)
pygame.draw.line(screen, colors["white"], dtod(points[5], scale).point,
dtod(points[6], scale).point)
pygame.draw.line(screen, colors["white"], dtod(points[6], scale).point,
dtod(points[7], scale).point)
pygame.draw.line(screen, colors["white"], dtod(points[7], scale).point,
dtod(points[4], scale).point)
pygame.draw.line(screen, colors["white"], dtod(points[0], scale).point,
dtod(points[4], scale).point)
pygame.draw.line(screen, colors["white"], dtod(points[5], scale).point,
dtod(points[1], scale).point)
pygame.draw.line(screen, colors["white"], dtod(points[6], scale).point,
dtod(points[2], scale).point)
pygame.draw.line(screen, colors["white"], dtod(points[7], scale).point,
dtod(points[3], scale).point)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
run = 0
if event.key == pygame.K_x:
x = 1
if event.key == pygame.K_y:
y = 1
if event.key == pygame.K_z:
z = 1
if event.key == pygame.K_UP:
if x == 1:
tx += math.pi / 180
if y == 1:
ty += math.pi / 180
if z == 1:
tz += math.pi / 180
if event.key == pygame.K_DOWN:
if x == 1:
tx -= math.pi / 180
if y == 1:
ty -= math.pi / 180
if z == 1:
tz -= math.pi / 180
if event.type == pygame.KEYUP:
if event.key == pygame.K_x:
x = 0
tx = 0
if event.key == pygame.K_y:
y = 0
ty = 0
if event.key == pygame.K_z:
z = 0
tz = 0
pygame.display.update()
pygame.quit()
The problem was that I was applying parallax method but in the wrong way. I didn't consider the position of camera. Notice, now I m subtracting and multiplying some value from self.point[0] i.e. x component and same with y component. That value is the distance from camera, which can easily be proved by similar triangles.
I have written a query which consists of multiple joins and sum(if()) condition.
I am using MySql Database.
The query structure seems like this:
*The query joins from multiple tables(7 to be precise) and the sum(if()) conditions is to represent total 53 states of US.*It takes almost 20 minutes for the query to execute which is a very long period.
If anyone could suggest how can I reduce this large amount of time.
SELECT ag.position_id AS 'position_id',
ag.npn AS 'NPN',
concat(ag.first_name, ' ', ag.last_name) AS 'full_name',
lb.name AS 'lob',
location_lic AS 'loc',
COUNT(DISTINCT lt.id) AS 'RTS_Total',
SUM(IF(st.id = 1, 1, 0)) AS 'AK',
SUM(IF(st.id = 2, 1, 0)) AS 'AL',
SUM(IF(st.id = 3, 1, 0)) AS 'AR',
SUM(IF(st.id = 4, 1, 0)) AS 'AZ',
SUM(IF(st.id = 5, 1, 0)) AS 'CA',
SUM(IF(st.id = 6, 1, 0)) AS 'CO',
SUM(IF(st.id = 7, 1, 0)) AS 'CT',
SUM(IF(st.id = 8, 1, 0)) AS 'DC',
SUM(IF(st.id = 9, 1, 0)) AS 'DE',
SUM(IF(st.id = 10, 1, 0)) AS 'FL',
SUM(IF(st.id = 11, 1, 0)) AS 'GA',
SUM(IF(st.id = 12, 1, 0)) AS 'HI',
SUM(IF(st.id = 13, 1, 0)) AS 'IA',
SUM(IF(st.id = 14, 1, 0)) AS 'ID',
SUM(IF(st.id = 15, 1, 0)) AS 'IL',
SUM(IF(st.id = 16, 1, 0)) AS 'IN',
SUM(IF(st.id = 17, 1, 0)) AS 'KS',
SUM(IF(st.id = 18, 1, 0)) AS 'KY',
SUM(IF(st.id = 19, 1, 0)) AS 'LA',
SUM(IF(st.id = 20, 1, 0)) AS 'MA',
SUM(IF(st.id = 21, 1, 0)) AS 'MD',
SUM(IF(st.id = 22, 1, 0)) AS 'ME',
SUM(IF(st.id = 23, 1, 0)) AS 'MI',
SUM(IF(st.id = 24, 1, 0)) AS 'MN',
SUM(IF(st.id = 25, 1, 0)) AS 'MO',
SUM(IF(st.id = 26, 1, 0)) AS 'MS',
SUM(IF(st.id = 27, 1, 0)) AS 'MT',
SUM(IF(st.id = 28, 1, 0)) AS 'NC',
SUM(IF(st.id = 29, 1, 0)) AS 'ND',
SUM(IF(st.id = 30, 1, 0)) AS 'NE',
SUM(IF(st.id = 31, 1, 0)) AS 'NH',
SUM(IF(st.id = 32, 1, 0)) AS 'NJ',
SUM(IF(st.id = 33, 1, 0)) AS 'NM',
SUM(IF(st.id = 34, 1, 0)) AS 'NV',
SUM(IF(st.id = 35, 1, 0)) AS 'NY',
SUM(IF(st.id = 36, 1, 0)) AS 'OH',
SUM(IF(st.id = 37, 1, 0)) AS 'OK',
SUM(IF(st.id = 38, 1, 0)) AS 'OR',
SUM(IF(st.id = 39, 1, 0)) AS 'PA',
SUM(IF(st.id = 40, 1, 0)) AS 'PR',
SUM(IF(st.id = 41, 1, 0)) AS 'RI',
SUM(IF(st.id = 42, 1, 0)) AS 'SC',
SUM(IF(st.id = 43, 1, 0)) AS 'SD',
SUM(IF(st.id = 44, 1, 0)) AS 'TN',
SUM(IF(st.id = 45, 1, 0)) AS 'TX',
SUM(IF(st.id = 46, 1, 0)) AS 'UT',
SUM(IF(st.id = 47, 1, 0)) AS 'VA',
SUM(IF(st.id = 48, 1, 0)) AS 'VI',
SUM(IF(st.id = 49, 1, 0)) AS 'VT',
SUM(IF(st.id = 50, 1, 0)) AS 'WA',
SUM(IF(st.id = 51, 1, 0)) AS 'WI',
SUM(IF(st.id = 52, 1, 0)) AS 'WV',
SUM(IF(st.id = 53, 1, 0)) AS 'WY'
FROM cxprtsapp_licensetracker lt
INNER JOIN cxprtsapp_agents ag ON ag.id = lt.agent_id_id AND ag.position_status LIKE 'Active'
LEFT JOIN cxprtsapp_statelobjit slj ON slj.state_id = lt.state_id_id AND ag.lob_id = slj.lob_id
LEFT JOIN
(select npn, rtsreport_appointed, rtsreport_licensed, state_id, lob_id
from cxprtsapp_rtslob
order BY refresh_number desc
) rts ON rts.state_id = lt.state_id_id and ag.lob_id = rts.lob_id and ag.npn=rts.npn
INNER JOIN cxprtsapp_location lc ON lc.id = ag.loc_id
INNER JOIN cxprtsapp_lineofbussiness lb ON lb.id = ag.lob_id
INNER JOIN cxprtsapp_states st ON st.id = lt.state_id_id
LEFT JOIN
(SELECT DISTINCT npn, state_code, status
FROM cxprtsapp_pdbappointments
WHERE status LIKE 'Appointed'
) appt ON appt.npn = ag.npn AND appt.state_code = st.state_code
WHERE certification_id IS NOT NULL
AND (expiration_date IS NULL OR expiration_date > CURDATE())
AND (slj.jit = 1 OR rts.rtsreport_appointed = 1 OR appt.status IS NOT NULL)
GROUP BY ag.id, ag.lob_id,loc_id ORDER BY ag.hire_date DESC;
Solution:
The time taken for the query has reduced from 10-15 min to 10-20 sec.
We must alter database index for performance.
we must the run the below sql query in the database first.
ALTER TABLE cxprtsapp_agents ADD INDEX cxprtsapp_agents_idx_status_id_id_npn_id (position_status,id,lob_id,npn,loc_id);
ALTER TABLE cxprtsapp_licensetracker ADD INDEX cxprtsapp_licensetra_idx_id_id_id_id (agent_id_id,state_id_id,certification_id,id);
ALTER TABLE cxprtsapp_lineofbussiness ADD INDEX cxprtsapp_lineofbuss_idx_id_name (id,name);
ALTER TABLE cxprtsapp_location ADD INDEX cxprtsapp_location_idx_id_lic (id,location_lic);
ALTER TABLE cxprtsapp_statelobjit ADD INDEX cxprtsapp_statelobji_idx_id_id (state_id,lob_id);
ALTER TABLE cxprtsapp_states ADD INDEX cxprtsapp_states_idx_id_code (id,state_code);
ALTER TABLE cxprtsapp_rtslob ADD INDEX cxprtsapp_rtslob_idx_numbe_npn_appoi_licen_id_id (refresh_number,npn,rtsreport_appointed,rtsreport_licensed,state_id,lob_id);
ALTER TABLE cxprtsapp_pdbappointments ADD INDEX cxprtsapp_pdbappoint_idx_status_npn_code (status,npn,state_code);
I am working on an app where user's current playing song title is fetched and we look in the mysql database to see who else is playing a similar song.since the same song might be with many varied titles on everyone's phone , we need a way to effectively find as close results as possible.
The process that we are using right now gets all the songs from the table then do a foreach and compare each entry in the resultset with user's song.
Here is a part of the function we have used:
$all_results = $db->select($sql);//all db entries from the songs table
foreach ( $all_results as $u ) {
$toTest = strtolower( $u['last_song'] );
$toTest = preg_replace('/[^A-Za-z0-9]/', ' ', $toTest);
$score = 0;
$score = $this->calSim( $user_last_song, $toTest, 0 ); //user last song is the current song being played by the user
if ( $score > 1 ) { //if at least there is some match then compare by another method
$score = $this->calMetaphone($user_last_song, $toTest, $score);
}
if ( $score > 5 ) {
//song matches.Push into a final array
}
}
=======================================
here are the 2 custom functions:
public function calMetaphone ( $x, $y, $pts ) {
$x = metaphone( $x );
$y = metaphone( $y );
$pts = $this->calSim( $x, $y, $pts );
return $pts;
}
public function calSim ( $x, $y, $pts ) {
similar_text($x, $y, $sim);
//echo "Similarity is :$sim<br>";
if ( $sim >= 90 ) {
$pts = $pts + 5;
} else if ( $sim >= 80 ) {
$pts = $pts + 4;
}
if ( $sim >= 70 ) {
$pts = $pts + 3;
}
if ( $sim >= 60 ) {
$pts = $pts + 2;
} else {
$pts = $pts + 0;
}
return $pts;
}
But I know this is a real bad way of doing it.If there are large number of entries in database it might take forever to compare them all 1 by 1.
Can anyone tell me the correct method that should be followed here.
Thanks
Karam
I can't take any credit for this but when I needed a similar function I found this (can't remember where though) for a metaphone:-
DROP FUNCTION `func_Double_Metaphone`//
CREATE DEFINER=`aaaa`#`%` FUNCTION `func_Double_Metaphone`(st VARCHAR(55)) RETURNS varchar(128) CHARSET utf8
NO SQL
BEGIN
DECLARE length, first, last, pos, prevpos, is_slavo_germanic SMALLINT;
DECLARE pri, sec VARCHAR(45) DEFAULT '';
DECLARE ch CHAR(1);
SET first = 3;
SET length = CHAR_LENGTH(st);
SET last = first + length -1;
SET st = CONCAT(REPEAT('-', first -1), UCASE(st), REPEAT(' ', 5)); SET is_slavo_germanic = (st LIKE '%W%' OR st LIKE '%K%' OR st LIKE '%CZ%'); SET pos = first; IF SUBSTRING(st, first, 2) IN ('GN', 'KN', 'PN', 'WR', 'PS') THEN
SET pos = pos + 1;
END IF;
IF SUBSTRING(st, first, 1) = 'X' THEN
SET pri = 'S', sec = 'S', pos = pos + 1; END IF;
WHILE pos <= last DO
SET prevpos = pos;
SET ch = SUBSTRING(st, pos, 1); CASE
WHEN ch IN ('A', 'E', 'I', 'O', 'U', 'Y') THEN
IF pos = first THEN SET pri = CONCAT(pri, 'A'), sec = CONCAT(sec, 'A'), pos = pos + 1; ELSE
SET pos = pos + 1;
END IF;
WHEN ch = 'B' THEN
IF SUBSTRING(st, pos+1, 1) = 'B' THEN
SET pri = CONCAT(pri, 'P'), sec = CONCAT(sec, 'P'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'P'), sec = CONCAT(sec, 'P'), pos = pos + 1; END IF;
WHEN ch = 'C' THEN
IF (pos > (first + 1) AND SUBSTRING(st, pos-2, 1) NOT IN ('A', 'E', 'I', 'O', 'U', 'Y') AND SUBSTRING(st, pos-1, 3) = 'ACH' AND
(SUBSTRING(st, pos+2, 1) NOT IN ('I', 'E') OR SUBSTRING(st, pos-2, 6) IN ('BACHER', 'MACHER'))) THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 2; ELSEIF pos = first AND SUBSTRING(st, first, 6) = 'CAESAR' THEN
SET pri = CONCAT(pri, 'S'), sec = CONCAT(sec, 'S'), pos = pos + 2; ELSEIF SUBSTRING(st, pos, 4) = 'CHIA' THEN SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 2; ELSEIF SUBSTRING(st, pos, 2) = 'CH' THEN
IF pos > first AND SUBSTRING(st, pos, 4) = 'CHAE' THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'X'), pos = pos + 2; ELSEIF pos = first AND (SUBSTRING(st, pos+1, 5) IN ('HARAC', 'HARIS') OR
SUBSTRING(st, pos+1, 3) IN ('HOR', 'HYM', 'HIA', 'HEM')) AND SUBSTRING(st, first, 5) != 'CHORE' THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 2; ELSEIF SUBSTRING(st, first, 4) IN ('VAN ', 'VON ') OR SUBSTRING(st, first, 3) = 'SCH'
OR SUBSTRING(st, pos-2, 6) IN ('ORCHES', 'ARCHIT', 'ORCHID')
OR SUBSTRING(st, pos+2, 1) IN ('T', 'S')
OR ((SUBSTRING(st, pos-1, 1) IN ('A', 'O', 'U', 'E') OR pos = first)
AND SUBSTRING(st, pos+2, 1) IN ('L', 'R', 'N', 'M', 'B', 'H', 'F', 'V', 'W', ' ')) THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 2; ELSE
IF pos > first THEN
IF SUBSTRING(st, first, 2) = 'MC' THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'X'), sec = CONCAT(sec, 'K'), pos = pos + 2; END IF;
ELSE
SET pri = CONCAT(pri, 'X'), sec = CONCAT(sec, 'X'), pos = pos + 2; END IF;
END IF;
ELSEIF SUBSTRING(st, pos, 2) = 'CZ' AND SUBSTRING(st, pos-2, 4) != 'WICZ' THEN
SET pri = CONCAT(pri, 'S'), sec = CONCAT(sec, 'X'), pos = pos + 2; ELSEIF SUBSTRING(st, pos+1, 3) = 'CIA' THEN
SET pri = CONCAT(pri, 'X'), sec = CONCAT(sec, 'X'), pos = pos + 3; ELSEIF SUBSTRING(st, pos, 2) = 'CC' AND NOT (pos = (first +1) AND SUBSTRING(st, first, 1) = 'M') THEN
IF SUBSTRING(st, pos+2, 1) IN ('I', 'E', 'H') AND SUBSTRING(st, pos+2, 2) != 'HU' THEN
IF (pos = first +1 AND SUBSTRING(st, first) = 'A') OR
SUBSTRING(st, pos-1, 5) IN ('UCCEE', 'UCCES') THEN
SET pri = CONCAT(pri, 'KS'), sec = CONCAT(sec, 'KS'), pos = pos + 3; ELSE
SET pri = CONCAT(pri, 'X'), sec = CONCAT(sec, 'X'), pos = pos + 3; END IF;
ELSE
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 2; END IF;
ELSEIF SUBSTRING(st, pos, 2) IN ('CK', 'CG', 'CQ') THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 2; ELSEIF SUBSTRING(st, pos, 2) IN ('CI', 'CE', 'CY') THEN
IF SUBSTRING(st, pos, 3) IN ('CIO', 'CIE', 'CIA') THEN
SET pri = CONCAT(pri, 'S'), sec = CONCAT(sec, 'X'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'S'), sec = CONCAT(sec, 'S'), pos = pos + 2; END IF;
ELSE
IF SUBSTRING(st, pos+1, 2) IN (' C', ' Q', ' G') THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 3; ELSE
IF SUBSTRING(st, pos+1, 1) IN ('C', 'K', 'Q') AND SUBSTRING(st, pos+1, 2) NOT IN ('CE', 'CI') THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 2; ELSE SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 1; END IF;
END IF;
END IF;
WHEN ch = 'D' THEN
IF SUBSTRING(st, pos, 2) = 'DG' THEN
IF SUBSTRING(st, pos+2, 1) IN ('I', 'E', 'Y') THEN SET pri = CONCAT(pri, 'J'), sec = CONCAT(sec, 'J'), pos = pos + 3; ELSE
SET pri = CONCAT(pri, 'TK'), sec = CONCAT(sec, 'TK'), pos = pos + 2; END IF;
ELSEIF SUBSTRING(st, pos, 2) IN ('DT', 'DD') THEN
SET pri = CONCAT(pri, 'T'), sec = CONCAT(sec, 'T'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'T'), sec = CONCAT(sec, 'T'), pos = pos + 1; END IF;
WHEN ch = 'F' THEN
IF SUBSTRING(st, pos+1, 1) = 'F' THEN
SET pri = CONCAT(pri, 'F'), sec = CONCAT(sec, 'F'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'F'), sec = CONCAT(sec, 'F'), pos = pos + 1; END IF;
WHEN ch = 'G' THEN
IF SUBSTRING(st, pos+1, 1) = 'H' THEN
IF (pos > first AND SUBSTRING(st, pos-1, 1) NOT IN ('A', 'E', 'I', 'O', 'U', 'Y'))
OR ( pos = first AND SUBSTRING(st, pos+2, 1) != 'I') THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 2; ELSEIF pos = first AND SUBSTRING(st, pos+2, 1) = 'I' THEN
SET pri = CONCAT(pri, 'J'), sec = CONCAT(sec, 'J'), pos = pos + 2; ELSEIF (pos > (first + 1) AND SUBSTRING(st, pos-2, 1) IN ('B', 'H', 'D') )
OR (pos > (first + 2) AND SUBSTRING(st, pos-3, 1) IN ('B', 'H', 'D') )
OR (pos > (first + 3) AND SUBSTRING(st, pos-4, 1) IN ('B', 'H') ) THEN
SET pos = pos + 2; ELSE
IF pos > (first + 2) AND SUBSTRING(st, pos-1, 1) = 'U'
AND SUBSTRING(st, pos-3, 1) IN ('C', 'G', 'L', 'R', 'T') THEN
SET pri = CONCAT(pri, 'F'), sec = CONCAT(sec, 'F'), pos = pos + 2; ELSEIF pos > first AND SUBSTRING(st, pos-1, 1) != 'I' THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 2; ELSE
SET pos = pos + 1;
END IF;
END IF;
ELSEIF SUBSTRING(st, pos+1, 1) = 'N' THEN
IF pos = (first +1) AND SUBSTRING(st, first, 1) IN ('A', 'E', 'I', 'O', 'U', 'Y') AND NOT is_slavo_germanic THEN
SET pri = CONCAT(pri, 'KN'), sec = CONCAT(sec, 'N'), pos = pos + 2; ELSE
IF SUBSTRING(st, pos+2, 2) != 'EY' AND SUBSTRING(st, pos+1, 1) != 'Y'
AND NOT is_slavo_germanic THEN
SET pri = CONCAT(pri, 'N'), sec = CONCAT(sec, 'KN'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'KN'), sec = CONCAT(sec, 'KN'), pos = pos + 2; END IF;
END IF;
ELSEIF SUBSTRING(st, pos+1, 2) = 'LI' AND NOT is_slavo_germanic THEN
SET pri = CONCAT(pri, 'KL'), sec = CONCAT(sec, 'L'), pos = pos + 2; ELSEIF pos = first AND (SUBSTRING(st, pos+1, 1) = 'Y'
OR SUBSTRING(st, pos+1, 2) IN ('ES', 'EP', 'EB', 'EL', 'EY', 'IB', 'IL', 'IN', 'IE', 'EI', 'ER')) THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'J'), pos = pos + 2; ELSEIF (SUBSTRING(st, pos+1, 2) = 'ER' OR SUBSTRING(st, pos+1, 1) = 'Y')
AND SUBSTRING(st, first, 6) NOT IN ('DANGER', 'RANGER', 'MANGER')
AND SUBSTRING(st, pos-1, 1) not IN ('E', 'I') AND SUBSTRING(st, pos-1, 3) NOT IN ('RGY', 'OGY') THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'J'), pos = pos + 2; ELSEIF SUBSTRING(st, pos+1, 1) IN ('E', 'I', 'Y') OR SUBSTRING(st, pos-1, 4) IN ('AGGI', 'OGGI') THEN
IF SUBSTRING(st, first, 4) IN ('VON ', 'VAN ') OR SUBSTRING(st, first, 3) = 'SCH'
OR SUBSTRING(st, pos+1, 2) = 'ET' THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 2; ELSE
IF SUBSTRING(st, pos+1, 4) = 'IER ' THEN
SET pri = CONCAT(pri, 'J'), sec = CONCAT(sec, 'J'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'J'), sec = CONCAT(sec, 'K'), pos = pos + 2; END IF;
END IF;
ELSEIF SUBSTRING(st, pos+1, 1) = 'G' THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 1; END IF;
WHEN ch = 'H' THEN
IF (pos = first OR SUBSTRING(st, pos-1, 1) IN ('A', 'E', 'I', 'O', 'U', 'Y'))
AND SUBSTRING(st, pos+1, 1) IN ('A', 'E', 'I', 'O', 'U', 'Y') THEN
SET pri = CONCAT(pri, 'H'), sec = CONCAT(sec, 'H'), pos = pos + 2; ELSE SET pos = pos + 1; END IF;
WHEN ch = 'J' THEN
IF SUBSTRING(st, pos, 4) = 'JOSE' OR SUBSTRING(st, first, 4) = 'SAN ' THEN
IF (pos = first AND SUBSTRING(st, pos+4, 1) = ' ') OR SUBSTRING(st, first, 4) = 'SAN ' THEN
SET pri = CONCAT(pri, 'H'), sec = CONCAT(sec, 'H'); ELSE
SET pri = CONCAT(pri, 'J'), sec = CONCAT(sec, 'H'); END IF;
ELSEIF pos = first AND SUBSTRING(st, pos, 4) != 'JOSE' THEN
SET pri = CONCAT(pri, 'J'), sec = CONCAT(sec, 'A'); ELSE
IF SUBSTRING(st, pos-1, 1) IN ('A', 'E', 'I', 'O', 'U', 'Y') AND NOT is_slavo_germanic
AND SUBSTRING(st, pos+1, 1) IN ('A', 'O') THEN
SET pri = CONCAT(pri, 'J'), sec = CONCAT(sec, 'H'); ELSE
IF pos = last THEN
SET pri = CONCAT(pri, 'J'); ELSE
IF SUBSTRING(st, pos+1, 1) not IN ('L', 'T', 'K', 'S', 'N', 'M', 'B', 'Z')
AND SUBSTRING(st, pos-1, 1) not IN ('S', 'K', 'L') THEN
SET pri = CONCAT(pri, 'J'), sec = CONCAT(sec, 'J'); END IF;
END IF;
END IF;
END IF;
IF SUBSTRING(st, pos+1, 1) = 'J' THEN
SET pos = pos + 2;
ELSE
SET pos = pos + 1;
END IF;
WHEN ch = 'K' THEN
IF SUBSTRING(st, pos+1, 1) = 'K' THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 1; END IF;
WHEN ch = 'L' THEN
IF SUBSTRING(st, pos+1, 1) = 'L' THEN
IF (pos = (last - 2) AND SUBSTRING(st, pos-1, 4) IN ('ILLO', 'ILLA', 'ALLE'))
OR ((SUBSTRING(st, last-1, 2) IN ('AS', 'OS') OR SUBSTRING(st, last) IN ('A', 'O'))
AND SUBSTRING(st, pos-1, 4) = 'ALLE') THEN
SET pri = CONCAT(pri, 'L'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'L'), sec = CONCAT(sec, 'L'), pos = pos + 2; END IF;
ELSE
SET pri = CONCAT(pri, 'L'), sec = CONCAT(sec, 'L'), pos = pos + 1; END IF;
WHEN ch = 'M' THEN
IF SUBSTRING(st, pos-1, 3) = 'UMB'
AND (pos + 1 = last OR SUBSTRING(st, pos+2, 2) = 'ER')
OR SUBSTRING(st, pos+1, 1) = 'M' THEN
SET pri = CONCAT(pri, 'M'), sec = CONCAT(sec, 'M'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'M'), sec = CONCAT(sec, 'M'), pos = pos + 1; END IF;
WHEN ch = 'N' THEN
IF SUBSTRING(st, pos+1, 1) = 'N' THEN
SET pri = CONCAT(pri, 'N'), sec = CONCAT(sec, 'N'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'N'), sec = CONCAT(sec, 'N'), pos = pos + 1; END IF;
WHEN ch = 'P' THEN
IF SUBSTRING(st, pos+1, 1) = 'H' THEN
SET pri = CONCAT(pri, 'F'), sec = CONCAT(sec, 'F'), pos = pos + 2; ELSEIF SUBSTRING(st, pos+1, 1) IN ('P', 'B') THEN SET pri = CONCAT(pri, 'P'), sec = CONCAT(sec, 'P'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'P'), sec = CONCAT(sec, 'P'), pos = pos + 1; END IF;
WHEN ch = 'Q' THEN
IF SUBSTRING(st, pos+1, 1) = 'Q' THEN
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'K'), sec = CONCAT(sec, 'K'), pos = pos + 1; END IF;
WHEN ch = 'R' THEN
IF pos = last AND not is_slavo_germanic
AND SUBSTRING(st, pos-2, 2) = 'IE' AND SUBSTRING(st, pos-4, 2) NOT IN ('ME', 'MA') THEN
SET sec = CONCAT(sec, 'R'); ELSE
SET pri = CONCAT(pri, 'R'), sec = CONCAT(sec, 'R'); END IF;
IF SUBSTRING(st, pos+1, 1) = 'R' THEN
SET pos = pos + 2;
ELSE
SET pos = pos + 1;
END IF;
WHEN ch = 'S' THEN
IF SUBSTRING(st, pos-1, 3) IN ('ISL', 'YSL') THEN
SET pos = pos + 1;
ELSEIF pos = first AND SUBSTRING(st, first, 5) = 'SUGAR' THEN
SET pri = CONCAT(pri, 'X'), sec = CONCAT(sec, 'S'), pos = pos + 1; ELSEIF SUBSTRING(st, pos, 2) = 'SH' THEN
IF SUBSTRING(st, pos+1, 4) IN ('HEIM', 'HOEK', 'HOLM', 'HOLZ') THEN
SET pri = CONCAT(pri, 'S'), sec = CONCAT(sec, 'S'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'X'), sec = CONCAT(sec, 'X'), pos = pos + 2; END IF;
ELSEIF SUBSTRING(st, pos, 3) IN ('SIO', 'SIA') OR SUBSTRING(st, pos, 4) = 'SIAN' THEN
IF NOT is_slavo_germanic THEN
SET pri = CONCAT(pri, 'S'), sec = CONCAT(sec, 'X'), pos = pos + 3; ELSE
SET pri = CONCAT(pri, 'S'), sec = CONCAT(sec, 'S'), pos = pos + 3; END IF;
ELSEIF (pos = first AND SUBSTRING(st, pos+1, 1) IN ('M', 'N', 'L', 'W')) OR SUBSTRING(st, pos+1, 1) = 'Z' THEN
SET pri = CONCAT(pri, 'S'), sec = CONCAT(sec, 'X'); IF SUBSTRING(st, pos+1, 1) = 'Z' THEN
SET pos = pos + 2;
ELSE
SET pos = pos + 1;
END IF;
ELSEIF SUBSTRING(st, pos, 2) = 'SC' THEN
IF SUBSTRING(st, pos+2, 1) = 'H' THEN
IF SUBSTRING(st, pos+3, 2) IN ('OO', 'ER', 'EN', 'UY', 'ED', 'EM') THEN
IF SUBSTRING(st, pos+3, 2) IN ('ER', 'EN') THEN
SET pri = CONCAT(pri, 'X'), sec = CONCAT(sec, 'SK'), pos = pos + 3; ELSE
SET pri = CONCAT(pri, 'SK'), sec = CONCAT(sec, 'SK'), pos = pos + 3; END IF;
ELSE
IF pos = first AND SUBSTRING(st, first+3, 1) not IN ('A', 'E', 'I', 'O', 'U', 'Y') AND SUBSTRING(st, first+3, 1) != 'W' THEN
SET pri = CONCAT(pri, 'X'), sec = CONCAT(sec, 'S'), pos = pos + 3; ELSE
SET pri = CONCAT(pri, 'X'), sec = CONCAT(sec, 'X'), pos = pos + 3; END IF;
END IF;
ELSEIF SUBSTRING(st, pos+2, 1) IN ('I', 'E', 'Y') THEN
SET pri = CONCAT(pri, 'S'), sec = CONCAT(sec, 'S'), pos = pos + 3; ELSE
SET pri = CONCAT(pri, 'SK'), sec = CONCAT(sec, 'SK'), pos = pos + 3; END IF;
ELSEIF pos = last AND SUBSTRING(st, pos-2, 2) IN ('AI', 'OI') THEN
SET sec = CONCAT(sec, 'S'), pos = pos + 1; ELSE
SET pri = CONCAT(pri, 'S'), sec = CONCAT(sec, 'S'); IF SUBSTRING(st, pos+1, 1) IN ('S', 'Z') THEN
SET pos = pos + 2;
ELSE
SET pos = pos + 1;
END IF;
END IF;
WHEN ch = 'T' THEN
IF SUBSTRING(st, pos, 4) = 'TION' THEN
SET pri = CONCAT(pri, 'X'), sec = CONCAT(sec, 'X'), pos = pos + 3; ELSEIF SUBSTRING(st, pos, 3) IN ('TIA', 'TCH') THEN
SET pri = CONCAT(pri, 'X'), sec = CONCAT(sec, 'X'), pos = pos + 3; ELSEIF SUBSTRING(st, pos, 2) = 'TH' OR SUBSTRING(st, pos, 3) = 'TTH' THEN
IF SUBSTRING(st, pos+2, 2) IN ('OM', 'AM') OR SUBSTRING(st, first, 4) IN ('VON ', 'VAN ')
OR SUBSTRING(st, first, 3) = 'SCH' THEN
SET pri = CONCAT(pri, 'T'), sec = CONCAT(sec, 'T'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, '0'), sec = CONCAT(sec, 'T'), pos = pos + 2; END IF;
ELSEIF SUBSTRING(st, pos+1, 1) IN ('T', 'D') THEN
SET pri = CONCAT(pri, 'T'), sec = CONCAT(sec, 'T'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'T'), sec = CONCAT(sec, 'T'), pos = pos + 1; END IF;
WHEN ch = 'V' THEN
IF SUBSTRING(st, pos+1, 1) = 'V' THEN
SET pri = CONCAT(pri, 'F'), sec = CONCAT(sec, 'F'), pos = pos + 2; ELSE
SET pri = CONCAT(pri, 'F'), sec = CONCAT(sec, 'F'), pos = pos + 1; END IF;
WHEN ch = 'W' THEN
IF SUBSTRING(st, pos, 2) = 'WR' THEN
SET pri = CONCAT(pri, 'R'), sec = CONCAT(sec, 'R'), pos = pos + 2; ELSEIF pos = first AND (SUBSTRING(st, pos+1, 1) IN ('A', 'E', 'I', 'O', 'U', 'Y')
OR SUBSTRING(st, pos, 2) = 'WH') THEN
IF SUBSTRING(st, pos+1, 1) IN ('A', 'E', 'I', 'O', 'U', 'Y') THEN
SET pri = CONCAT(pri, 'A'), sec = CONCAT(sec, 'F'), pos = pos + 1; ELSE
SET pri = CONCAT(pri, 'A'), sec = CONCAT(sec, 'A'), pos = pos + 1; END IF;
ELSEIF (pos = last AND SUBSTRING(st, pos-1, 1) IN ('A', 'E', 'I', 'O', 'U', 'Y'))
OR SUBSTRING(st, pos-1, 5) IN ('EWSKI', 'EWSKY', 'OWSKI', 'OWSKY')
OR SUBSTRING(st, first, 3) = 'SCH' THEN
SET sec = CONCAT(sec, 'F'), pos = pos + 1; ELSEIF SUBSTRING(st, pos, 4) IN ('WICZ', 'WITZ') THEN
SET pri = CONCAT(pri, 'TS'), sec = CONCAT(sec, 'FX'), pos = pos + 4; ELSE SET pos = pos + 1;
END IF;
WHEN ch = 'X' THEN
IF not(pos = last AND (SUBSTRING(st, pos-3, 3) IN ('IAU', 'EAU')
OR SUBSTRING(st, pos-2, 2) IN ('AU', 'OU'))) THEN
SET pri = CONCAT(pri, 'KS'), sec = CONCAT(sec, 'KS'); END IF;
IF SUBSTRING(st, pos+1, 1) IN ('C', 'X') THEN
SET pos = pos + 2;
ELSE
SET pos = pos + 1;
END IF;
WHEN ch = 'Z' THEN
IF SUBSTRING(st, pos+1, 1) = 'H' THEN
SET pri = CONCAT(pri, 'J'), sec = CONCAT(sec, 'J'), pos = pos + 1; ELSEIF SUBSTRING(st, pos+1, 3) IN ('ZO', 'ZI', 'ZA')
OR (is_slavo_germanic AND pos > first AND SUBSTRING(st, pos-1, 1) != 'T') THEN
SET pri = CONCAT(pri, 'S'), sec = CONCAT(sec, 'TS'); ELSE
SET pri = CONCAT(pri, 'S'), sec = CONCAT(sec, 'S'); END IF;
IF SUBSTRING(st, pos+1, 1) = 'Z' THEN
SET pos = pos + 2;
ELSE
SET pos = pos + 1;
END IF;
ELSE
SET pos = pos + 1; END CASE;
IF pos = prevpos THEN
SET pos = pos +1;
SET pri = CONCAT(pri,'<didnt incr>'); END IF;
END WHILE;
IF pri != sec THEN
SET pri = CONCAT(pri, ';', sec);
END IF;
RETURN (pri);
END
I also needed a levenshtein function and managed to sort out one of those, but performance was such (when comparing values from many rows) that it was far faster to read the rows and use the php built in levenshtein function.