Skip to content

Commit e2dac17

Browse files
committed
Optimized fix point function
1 parent c987a99 commit e2dac17

4 files changed

Lines changed: 86 additions & 78 deletions

File tree

docs/js/class_p.js

Lines changed: 74 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -548,10 +548,10 @@ class Puzzle {
548548
// For this function to work correctly, cells need to have their surrond to be exact and their neighbor to contain all correct edges (there may be more edges than the correct ones)
549549
// This function fills in the rest of the fields, and modify incorrect fields if needed
550550

551-
fix_points(point, fix_adjacent = true, off_centered = false) {
551+
fix_points(point) {
552552
// First pass - reset fields
553553
for (var i in point) {
554-
if (this.types[0].indexOf(point[i].type) !== -1 && fix_adjacent) {
554+
if (this.types[0].indexOf(point[i].type) !== -1) {
555555
point[i].adjacent = [];
556556
}
557557
if (this.types[1].indexOf(point[i].type) !== -1) {
@@ -579,40 +579,24 @@ class Puzzle {
579579
for (let j = 0; j < vertices.length; j++) {
580580
point[vertices[j]].neighbor.push(parseInt(i));
581581
for (let k = j + 1; k < vertices.length; k++) {
582+
let not_connected = false;
582583
let vertex1 = point[vertices[j]];
583584
let vertex2 = point[vertices[k]];
584-
if (Math.abs(vertex1.x - vertex2.x) < 0.001) {
585-
for (let l = 0; l < edge_bank.length; l++) {
586-
if (Math.abs(point[edge_bank[l]].x - vertex1.x) < 0.001) {
587-
if ((!off_centered && (Math.abs(vertex1.y + vertex2.y - 2*point[edge_bank[l]].y) < 0.001)) || (off_centered && (vertex1.y < point[edge_bank[l]].y === point[edge_bank[l]].y < vertex2.y))) {
588-
deltas.push({diff: 0,
589-
v1: Math.min(vertices[j], vertices[k]),
590-
v2: Math.max(vertices[j], vertices[k]),
591-
edge: edge_bank[l]});
592-
}
585+
for (let l = 0; l < vertices.length; l++) {
586+
if (l !== j && l !== k) {
587+
if ((this.distance_to_line(vertex1, vertex2, point[vertices[l]]) < 0.001) && this.between_points(vertex1, vertex2, point[vertices[l]])) {
588+
not_connected = true;
593589
}
594590
}
595-
} else if (Math.abs(vertex1.y - vertex2.y) < 0.001) {
596-
for (let l = 0; l < edge_bank.length; l++) {
597-
if (Math.abs(point[edge_bank[l]].y - vertex1.y) < 0.001) {
598-
if ((!off_centered && (Math.abs(vertex1.x + vertex2.x - 2*point[edge_bank[l]].x) < 0.001)) || (off_centered && (vertex1.x < point[edge_bank[l]].x === point[edge_bank[l]].x < vertex2.x))) {
599-
deltas.push({diff: 0,
600-
v1: Math.min(vertices[j], vertices[k]),
601-
v2: Math.max(vertices[j], vertices[k]),
602-
edge: edge_bank[l]});
603-
}
604-
}
605-
}
606-
} else {
591+
}
592+
if (!not_connected) {
607593
for (let l = 0; l < edge_bank.length; l++) {
608-
let delta = Math.abs(((vertex1.y - point[edge_bank[l]].y)*(vertex2.x - point[edge_bank[l]].x)) -
609-
((vertex1.x - point[edge_bank[l]].x)*(vertex2.y - point[edge_bank[l]].y)));
610-
if ((!off_centered && (Math.abs(vertex1.x + vertex2.x - 2*point[edge_bank[l]].x) < 0.001) && (Math.abs(vertex1.y + vertex2.y - 2*point[edge_bank[l]].y) < 0.001) ) ||
611-
(off_centered && (vertex1.x < point[edge_bank[l]].x === point[edge_bank[l]].x < vertex2.x) && (vertex1.y < point[edge_bank[l]].y === point[edge_bank[l]].y < vertex2.y))) {
594+
let delta = this.distance_to_line(vertex1, vertex2, point[edge_bank[l]]);
595+
if (this.between_points(vertex1, vertex2, point[edge_bank[l]])) {
612596
deltas.push({diff: delta,
613-
v1: Math.min(vertices[j], vertices[k]),
614-
v2: Math.max(vertices[j], vertices[k]),
615-
edge: edge_bank[l]});
597+
v1: Math.min(vertices[j], vertices[k]),
598+
v2: Math.max(vertices[j], vertices[k]),
599+
edge: edge_bank[l]});
616600
}
617601
}
618602
}
@@ -624,12 +608,6 @@ class Puzzle {
624608
for (let j = 0; j < vertices.length; j++) {
625609
// Fill in the edge_to_vertex data, and add the cell to the edge's neighbour
626610
point[deltas[j].edge].edge_to_vertex = [deltas[j].v1, deltas[j].v2];
627-
if (point[deltas[j].v1].edge_to_vertex.indexOf(deltas[j].edge) < 0) {
628-
point[deltas[j].v1].edge_to_vertex.push(deltas[j].edge);
629-
}
630-
if (point[deltas[j].v2].edge_to_vertex.indexOf(deltas[j].edge) < 0) {
631-
point[deltas[j].v2].edge_to_vertex.push(deltas[j].edge);
632-
}
633611
point[deltas[j].edge].neighbor.push(parseInt(i));
634612
edges.push(deltas[j].edge);
635613
}
@@ -649,10 +627,15 @@ class Puzzle {
649627
}
650628
}
651629
// Fix cells adjacent
652-
if (edge.neighbor.length == 2 && fix_adjacent) {
630+
if (edge.neighbor.length == 2) {
653631
point[edge.neighbor[j]].adjacent.push(parseInt(edge.neighbor[(j + 1) % 2]));
654632
}
655633
}
634+
// Fix vertices' edge_to_vertex
635+
if (!!edge.edge_to_vertex) {
636+
for (let j = 0; j < edge.edge_to_vertex.length; j++)
637+
point[edge.edge_to_vertex[j]].edge_to_vertex.push(parseInt(i));
638+
}
656639
}
657640
}
658641
return point;
@@ -667,14 +650,18 @@ class Puzzle {
667650
let vertices = edge.edge_to_vertex;
668651
if (vertices.length == 2) {
669652
for (let j = 0; j < cells.length; j++) {
670-
point[this.corner_table[cells[j]][vertices[0]]].adjacent.push(parseInt(this.corner_table[cells[j]][vertices[1]]));
671-
point[this.corner_table[cells[j]][vertices[1]]].adjacent.push(parseInt(this.corner_table[cells[j]][vertices[0]]));
653+
if (!!point[this.corner_table[cells[j]][vertices[0]]] && !!point[this.corner_table[cells[j]][vertices[1]]]) {
654+
point[this.corner_table[cells[j]][vertices[0]]].adjacent.push(parseInt(this.corner_table[cells[j]][vertices[1]]));
655+
point[this.corner_table[cells[j]][vertices[1]]].adjacent.push(parseInt(this.corner_table[cells[j]][vertices[0]]));
656+
}
672657
}
673658
}
674659
if (cells.length == 2) {
675660
for (let j = 0; j < 2; j++) {
676-
point[this.corner_table[cells[1]][vertices[j]]].adjacent.push(parseInt(this.corner_table[cells[0]][vertices[j]]));
677-
point[this.corner_table[cells[0]][vertices[j]]].adjacent.push(parseInt(this.corner_table[cells[1]][vertices[j]]));
661+
if (!!point[this.corner_table[cells[0]][vertices[j]]] && !!point[this.corner_table[cells[1]][vertices[j]]]) {
662+
point[this.corner_table[cells[1]][vertices[j]]].adjacent.push(parseInt(this.corner_table[cells[0]][vertices[j]]));
663+
point[this.corner_table[cells[0]][vertices[j]]].adjacent.push(parseInt(this.corner_table[cells[1]][vertices[j]]));
664+
}
678665
}
679666
}
680667
}
@@ -687,7 +674,7 @@ class Puzzle {
687674
let cells = [];
688675
let corners = [];
689676
for (var i in point) {
690-
if (this.types[0].indexOf(point[i].type) !== -1 && point[i].use !== -1) {
677+
if (this.types[0].indexOf(point[i].type) !== -1) {
691678
cells.push(parseInt(i));
692679
}
693680
if (this.types[3].indexOf(point[i].type) !== -1) {
@@ -702,13 +689,12 @@ class Puzzle {
702689
let cell = point[cells[i]];
703690
for (let j = 0; j < cell.surround.length; j++) {
704691
let vertex = point[cell.surround[j]];
705-
let min = Number.MAX_VALUE;
692+
let min = 1;
706693
let corner = 0;
707694
for (let k = 0; k < corners.length; k++) {
708695
let corner_point = point[corners[k]];
709-
let diff = Math.abs((cell.y - vertex.y)*corner_point.x - (cell.x - vertex.x)*corner_point.y + (cell.x * vertex.y) - (cell.y * vertex.x)) /
710-
Math.sqrt((cell.y - vertex.y)**2 + (cell.x - vertex.x)**2);
711-
if ((min > diff) && (cell.x > point[corners[k]].x === point[corners[k]].x > vertex.x) && (cell.y > point[corners[k]].y === point[corners[k]].y > vertex.y)) {
696+
let diff = this.distance_to_line(cell, vertex, corner_point);
697+
if ((min > diff) && (Math.min(vertex.use, cell.use) !== -1) && this.between_points(vertex, cell, corner_point)) {
712698
min = diff;
713699
corner = corners[k];
714700
}
@@ -717,13 +703,30 @@ class Puzzle {
717703
point[corner].surround.push(parseInt(cell.surround[j]));
718704
point[corner].neighbor.push(parseInt(cells[i]));
719705
this.corner_table[cells[i]][cell.surround[j]] = corner;
720-
this.remove_from_array(corners, corner);
721706
}
722707
}
723708
}
724709
return point;
725710
}
726711

712+
// Helper functions
713+
distance_to_line(line1, line2, point) {
714+
if (!line1 || !line2 || !point) {
715+
return Number.MAX_VALUE;
716+
}
717+
return Math.abs((line1.y - line2.y)*point.x - (line1.x - line2.x)*point.y + (line1.x * line2.y) - (line1.y * line2.x)) /
718+
Math.sqrt((line1.y - line2.y)**2 + (line1.x - line2.x)**2);
719+
}
720+
721+
between_points(p1, p2, test) {
722+
if (!p1 || !p2 || !test) {
723+
return false;
724+
}
725+
return (Math.min(p1.x,p2.x) <= (test.x + 0.00001)) && ((test.x - 0.00001) <= Math.max(p1.x, p2.x)) &&
726+
(Math.min(p1.y,p2.y) <= (test.y + 0.00001)) && ((test.y - 0.00001) <= Math.max(p1.y, p2.y));
727+
}
728+
729+
727730
// Create corners to be used by the puzzle
728731
create_corners(point, radius, k) {
729732
for (var i in point) {
@@ -9624,9 +9627,9 @@ class Puzzle {
96249627

96259628

96269629
let line_style = this.mode[this.mode.qa][this.mode[this.mode.qa].edit_mode][1];
9627-
// Find if any cell of the new cage (if square grid) has outside half grid cells then skip
9630+
// Find if any cell of the new cage has outside half grid cells then skip
96289631
for (let i = 0; i < this.cageselection.length; i++) {
9629-
if (this.cell_outside_for_square(this.cageselection[i])) {
9632+
if (this.cell_outside(this.cageselection[i])) {
96309633
cageexist_status = true;
96319634
skip_cages = true;
96329635
break;
@@ -9834,7 +9837,7 @@ class Puzzle {
98349837
while (cage_queue.length > 0) {
98359838
let cell = cage_queue.shift();
98369839
found_cage.push(cell);
9837-
if (this.cell_outside_for_square(cell) || !this.corner_table[cell]) {
9840+
if (this.cell_outside(cell) || !this.corner_table[cell]) {
98389841
not_in_cage = true;
98399842
break;
98409843
}
@@ -9883,7 +9886,7 @@ class Puzzle {
98839886
while (flood_queue.length > 0) {
98849887
let cell = flood_queue.shift();
98859888
context.push(cell);
9886-
if (this.cell_outside_for_square(cell)) {
9889+
if (this.cell_outside(cell)) {
98879890
full = true;
98889891
break;
98899892
}
@@ -9928,7 +9931,7 @@ class Puzzle {
99289931
while (temp_queue.length > 0) {
99299932
let cell = temp_queue.shift();
99309933
temp_area.push(cell);
9931-
if (this.cell_outside_for_square(cell) || !this.corner_table[cell]) {
9934+
if (this.cell_outside(cell) || !this.corner_table[cell]) {
99329935
reached_outside = true;
99339936
break;
99349937
}
@@ -9962,15 +9965,13 @@ class Puzzle {
99629965
return output;
99639966
}
99649967

9965-
// Returns true if a cell is partly outside on a square grid
9966-
cell_outside_for_square(cell) {
9967-
if (this.grid_is_square()) {
9968-
let row_size = parseInt(this.ny0 - 4);
9969-
let col_size = parseInt(this.nx0 - 4);
9970-
let col_num = (cell % (this.nx0)) - 2;
9971-
let row_num = parseInt(cell / this.nx0) - 2;
9972-
9973-
if ((row_num < 0) || (row_num >= row_size) || (col_num < 0) || (col_num >= col_size)) {
9968+
// Returns true if a cell is partly outside
9969+
cell_outside(cell) {
9970+
if (!cell) {
9971+
return true;
9972+
}
9973+
for (let i = 0; i < this.point[cell].surround.length; i++) {
9974+
if (!this.between_points({x: -1, y: -1}, {x: this.canvasx + 1, y: this.canvasy + 1}, this.point[this.point[cell].surround[i]])) {
99749975
return true;
99759976
}
99769977
}
@@ -13023,11 +13024,19 @@ class Puzzle {
1302313024
// i1-j1 and i2-j2 can define lines. Find the intersection of both lines, and connect the intersection to i1, then the intersection to i2
1302413025
let pi1 = this.get_cage_coordinates(i1, r);
1302513026
let pi2 = this.get_cage_coordinates(i2, r);
13026-
let pj1 = this.get_cage_coordinates(j1, r);
13027-
let pj2 = this.get_cage_coordinates(j2, r);
13027+
let pj1, pj2, denom;
13028+
let skip = false;
1302813029
let intersect = [];
13029-
13030-
let denom = ((pj2[1] - pi2[1]) * (pj1[0] - pi1[0])) - ((pj2[0] - pi2[0]) * (pj1[1] - pi1[1]));
13030+
if (!this.point[j1] || !this.point[j2]) {
13031+
// Cannot find the other points for some reason
13032+
skip = true;
13033+
denom = 0;
13034+
}
13035+
if (!skip) {
13036+
pj1 = this.get_cage_coordinates(j1, r);
13037+
pj2 = this.get_cage_coordinates(j2, r);
13038+
denom = ((pj2[1] - pi2[1]) * (pj1[0] - pi1[0])) - ((pj2[0] - pi2[0]) * (pj1[1] - pi1[1]));
13039+
}
1303113040
if (Math.abs(denom) < 0.0001 ) {
1303213041
// Undefined intersection, just take midpoint
1303313042
intersect = [(pi1[0] + pi2[0]) / 2, (pi1[1] + pi2[1]) / 2];

docs/js/class_pyramid.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -189,17 +189,18 @@ class Puzzle_pyramid extends Puzzle {
189189
}
190190
*/
191191
this.types = [[0], [1], [2, 3], [4, 6], []];
192-
this.point = this.point_connect_corners(this.point_fillin_corners(this.fix_points(point, false)));
192+
this.point = this.point_connect_corners(this.point_fillin_corners(this.fix_points(point)));
193193
}
194194

195195
listappend(centerlist) {
196196
var n = centerlist.length;
197197
for (var j = 0; j < n; j++) {
198-
if (centerlist.indexOf(this.point[centerlist[j]].adjacent[4]) === -1) {
199-
centerlist.push(this.point[centerlist[j]].adjacent[4]);
200-
}
201-
if (centerlist.indexOf(this.point[centerlist[j]].adjacent[5]) === -1) {
202-
centerlist.push(this.point[centerlist[j]].adjacent[5]);
198+
for (let k = 0; k < this.point[centerlist[j]].adjacent.length; k++) {
199+
if (this.point[centerlist[j]].y < this.point[this.point[centerlist[j]].adjacent[k]].y) {
200+
if (centerlist.indexOf(this.point[centerlist[j]].adjacent[k]) === -1) {
201+
centerlist.push(this.point[centerlist[j]].adjacent[k])
202+
}
203+
}
203204
}
204205
}
205206
return centerlist;

docs/js/class_uniform.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2968,7 +2968,7 @@ class Puzzle_tetrakis_square extends Puzzle_truncated_square {
29682968
point[point[i].surround[k]].use = 1;
29692969
}
29702970
}
2971-
this.point = this.point_connect_corners(this.create_corners(this.fix_points(point, true, true), 0.25, this.fix_points(point, true, true).length + 1)[0]);
2971+
this.point = this.point_connect_corners(this.create_corners(this.fix_points(point), 0.25, this.fix_points(point).length + 1)[0]);
29722972
}
29732973

29742974
reset_frame() {
@@ -7020,7 +7020,7 @@ class Puzzle_deltoidal_trihexagonal extends Puzzle_truncated_square {
70207020
point[i].surround[3] = s0;
70217021
}
70227022
}
7023-
this.point = this.point_connect_corners(this.create_corners(this.fix_points(point, true, true), 0.25, this.fix_points(point, true, true).length + 1)[0]);
7023+
this.point = this.point_connect_corners(this.create_corners(this.fix_points(point), 0.25, this.fix_points(point).length + 1)[0]);
70247024
}
70257025

70267026
reset_frame() {

docs/points.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,13 @@ These are used for compass clues, principally. These should usually be defined a
5454

5555
## Helper functions
5656

57-
### `fix_points(point, fix_adjacent, off_centered)`
57+
### `fix_points(point)`
5858
Build some associations given the following are defined within `point`:
5959
- Vertices and edges' coordinates.
6060
- Cells' `surround`
61-
- Cells' `neighbor` (there can be incorrect edges, as long as all correct ones are present). Returns the updated point array.
61+
- Cells' `neighbor` (there can be incorrect edges, as long as all correct ones are present).
6262

63-
The function will not build cells' `adjacent_dia`, vertices' `adjacent_dia`, edges' `adjacent` and all compass and corner attributes. Returns the updated point array. `fix_adjacent` defaults to being true, but
64-
can be set to false if the cells' adjacent are already filled. `off_centered` defaults to false, but can be
65-
set to true if the edges' "centers" are not in the middle of the edge.
63+
The function will not build cells' `adjacent_dia`, vertices' `adjacent_dia`, edges' `adjacent` and all compass and corner attributes. Returns the updated point array.
6664

6765
### `point_connect_corners(point)`
6866
Fill in the `adjacent` field of corners. `corner_table`, edges' `edge_to_vertex` and edges' `neighbor` must be filled beforehand. Returns the updated point array.

0 commit comments

Comments
 (0)