no more memory for NDSolve - pde

I am Solving a nonlinear partial differential equation and I have to apply very small steps since I am dealing with a physical phenomenon.But as I decrease the step size and even I am using MaxSteps, I still get the error no more memory for NDSolve.
Here is my program:
a = 0.05; b = 0.5; L = 20; T = 6 \[Pi]; h = 4;
NDSolve[{b*D[u[t, x], t, t] + a*D[u[t, x], t] ==
D[u[t, x], x, x] - Sin[u[t, x]], u[0, x] == 0,
Derivative[1, 0][u][0, x] == 0,
Derivative[0, 1][u][t, 0] == h*Sin[t],
Derivative[0, 1][u][t, L] == 0}, u, {t, 0, T}, {x, 0, L},
MaxStepSize -> 0.0001, MaxSteps -> 10^6]

Related

Maximize A[i]*B[i] + A[i]*B[j] + A[j]*B[j], i != j, given two unordered lists of positive integers

Can you help me with the algorithm:
Given 2 arrays of equal size a[] and b[] with integer numbers greater or equal to 1.
Find non-equal indices i and j (i != j) such that the value -
max(a[i]*b[i] + a[i] * b[j] + a[j] * b[j], a[i]*b[i] + a[j] * b[i] + a[j] * b[j])
will be maximum.
Example:
a = [1, 9, 6, 6] and b = [9, 1, 6, 6].
Maximum will be at i = 2 and j = 3 (zero-based indexing):
a[2]*b[2] + a[2]*b[3] + a[3] * b[3] = 6*6+6*6+6*6 = 108
Is there a way to find i and j in less then quadratic time?
And the same question for finding objective function value in less then quadratic time?
Thank you!
Here's my attempt at implementing David Eisenstat's idea. I think the i != j restriction made this more complicated but either way, I'd welcome suggestions on improving the code. There's a test at the end against brute force.
The construction of the upper envelope for the lines A[i]*x + A[i]*B[i] relies on Andrew's monotone chain convex hull algorithm applied to the dual points transformed from the lines.
Python code:
# Upper envelope of lines in the plane
from fractions import Fraction
import collections
def get_dual_point(line):
return (line[0], -line[1])
def get_primal_point(dual_line):
return (dual_line[0], -dual_line[1])
def get_line_from_two_points(p1, p2):
if p1[0] == p2[0]:
return (float('inf'), 0)
m = Fraction(p1[1] - p2[1], p1[0] - p2[0])
b = -m * p1[0] + p1[1]
return (m, b)
def cross_product(o, a, b):
return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])
# lower_hull has the structure [(dual_point, original_line, leftmost_x, index)]
def get_segment_idx(lower_hull, x):
lo = 0
hi = len(lower_hull) - 1
# Find the index of the first
# x coordinate greater than x
while lo < hi:
mid = lo + (hi - lo + 1) // 2
if lower_hull[mid][2] <= x:
lo = mid
else:
hi = mid - 1
return lo
# Assumes we add points in order of increasing x-coordinates
def add_right_to_lower_hull(lower_hull, point):
while len(lower_hull) > 0 and lower_hull[-1][0][0] == point[0][0] and lower_hull[-1][0][1] > point[0][1]:
lower_hull.pop()
while len(lower_hull) > 1 and cross_product(lower_hull[-2][0], lower_hull[-1][0], point[0]) <= 0:
lower_hull.pop()
if not lower_hull or lower_hull[-1][0][0] != point[0][0]:
lower_hull.append(point)
# Each segment of the lower hull
# in the dual plane is a line intersection
# in the primal plane.
if len(lower_hull) == 1:
lower_hull[0][2] = -float('inf')
else:
line = get_line_from_two_points(lower_hull[-1][0], lower_hull[-2][0])
lower_hull[-1][2] = get_primal_point(line)[0]
return lower_hull
# Assumes we add points in order of decreasing x-coordinates
def add_left_to_lower_hull(lower_hull, point):
while len(lower_hull) > 0 and lower_hull[0][0][0] == point[0][0] and lower_hull[0][0][1] > point[0][1]:
lower_hull.popleft()
while len(lower_hull) > 1 and cross_product(lower_hull[1][0], lower_hull[0][0], point[0]) >= 0:
lower_hull.popleft()
if not lower_hull or lower_hull[0][0][0] != point[0][0]:
lower_hull.appendleft(point)
# Each segment of the lower hull
# in the dual plane is a line intersection
# in the primal plane.
if len(lower_hull) == 1:
lower_hull[0][2] = -float('inf')
else:
line = get_line_from_two_points(lower_hull[0][0], lower_hull[1][0])
lower_hull[1][2] = get_primal_point(line)[0]
return lower_hull
# Maximise A[i] * B[i] + A[i] * B[j] + A[j] * B[j]
def f(A, B):
debug = False
if debug:
print("A: %s" % A)
print("B: %s" % B)
best = -float('inf')
best_idxs = ()
indexed_lines = [((A[i], A[i] * B[i]), i) for i in range(len(A))]
# Convert to points in the dual plane
# [dual_point, original_line, leftmost x coordinate added later, original index]
dual_points = [[get_dual_point(line), line, None, i] for line, i in indexed_lines]
# Sort points by x coordinate ascending
sorted_points = sorted(dual_points, key=lambda x: x[0][0])
if debug:
print("sorted points")
print(sorted_points)
# Build lower hull, left to right
lower_hull = []
add_right_to_lower_hull(lower_hull, sorted_points[0])
for i in range (1, len(sorted_points)):
# Query the point before inserting it
# because of the stipulation that i != j
idx = sorted_points[i][3]
segment_idx = get_segment_idx(lower_hull, B[idx])
m, b = lower_hull[segment_idx][1]
j = lower_hull[segment_idx][3]
candidate = m * B[idx] + b + A[idx] * B[idx]
if debug:
print("segment: %s, idx: %s, B[idx]: %s" % (segment_idx, idx, B[idx]))
if candidate > best:
best = candidate
best_idxs = (idx, j)
add_right_to_lower_hull(lower_hull, sorted_points[i])
if debug:
print("lower hull")
print(lower_hull)
# Build lower hull, right to left
lower_hull = collections.deque()
lower_hull.append(sorted_points[len(sorted_points) - 1])
for i in range (len(sorted_points) - 2, -1, -1):
# Query the point before inserting it
# because of the stipulation that i != j
idx = sorted_points[i][3]
segment_idx = get_segment_idx(lower_hull, B[idx])
m, b = lower_hull[segment_idx][1]
j = lower_hull[segment_idx][3]
candidate = m * B[idx] + b + A[idx] * B[idx]
if debug:
print("segment: %s, idx: %s, B[idx]: %s" % (segment_idx, idx, B[idx]))
if candidate > best:
best = candidate
best_idxs = (idx, j)
add_left_to_lower_hull(lower_hull, sorted_points[i])
if debug:
print("lower hull")
print(lower_hull)
return best, best_idxs
#A = [1, 9, 6, 6]
#B = [9, 1, 6, 6]
#print("")
#print(f(A, B))
# Test
import random
def brute_force(A, B):
best = -float('inf')
best_idxs = ()
for i in range(len(A)):
for j in range(len(B)):
if i != j:
candidate = A[i] * B[i] + A[i] * B[j] + A[j] * B[j]
if candidate > best:
best = candidate
best_idxs = (i, j)
return best, best_idxs
num_tests = 500
n = 20
m = 1000
for _ in range(num_tests):
A = [random.randint(1, m) for i in range(n)]
B = [random.randint(1, m) for i in range(n)]
_f = f(A, B)
_brute = brute_force(A, B)
if _f[0] != _brute[0]:
print("Mismatch")
print(A)
print(B)
print(_f, _brute)
print("Done testing.")
Yes, there’s an O(n log n)-time algorithm.
If we look at the function f(x) = max {a[i] b[i] + a[i] x | i},
it traces out a lower (convex) hull. It basically suffices to evaluate
f(b[j]) + a[j] b[j] for every j, with the one sticking point that
we need i ≠ j.
To fix that problem, we turn to an incremental hull algorithm with
amortized O(log n)-time insertions. The canonical algorithm keeps the
hull in sorted order, allowing for O(log n)-time queries. Starting with
an empty hull, for each index i, we query i and then insert i. Do this
once in forward order and once in reverse order, and take the max.

How do I fix warped walls in my raycaster?

I am writing a raycaster using the SDL library with C. I have been dealing with the fisheye effect for many weeks now. For a field of view like 60 degrees, I multiply the distance to the wall by the cosine of the relative angle (ranging from -30 to 30), but still, I get the same fisheye. Here's what that looks like:
I don't know what to do at this point, given that so many sources have recommended cosine correction and it just does not fix the distortion in my case.
I am compiling like this:
clang `pkg-config --cflags --libs sdl2` raycaster.c
To go forward and back, press the up and down keys. Press left and right to strafe. You can use the a and s keys to turn left and right respectively.
My code is below if you want to take a look. If you manage to figure out why I am getting a warped perspective in my engine, please let me know.
#include <SDL2/SDL.h>
#include <math.h>
#define SET_COLOR(r, g, b) SDL_SetRenderDrawColor(renderer, r, g, b, SDL_ALPHA_OPAQUE)
typedef struct {
float x, y, prev_x, prev_y, angle, fov;
} Player;
enum {
map_width = 12, map_height = 15,
screen_width = 800, screen_height = 500
};
const float
move_speed_decr = 0.08,
angle_turn = 2.0,
theta_step = 0.05,
dist_step = 0.8,
width_ratio = (float) screen_width / map_width,
height_ratio = (float) screen_height / map_height;
const unsigned char map[map_height][map_width] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1},
{1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1},
{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1},
{1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
SDL_Window* window;
SDL_Renderer* renderer;
float to_radians(float degrees) {
return degrees * (M_PI / 180.0f);
}
void draw_rectangle(SDL_Rect rectangle, int r, int g, int b) {
SET_COLOR(r, g, b);
SDL_RenderFillRect(renderer, &rectangle);
SDL_RenderDrawRect(renderer, &rectangle);
}
void raycast(Player player) {
SET_COLOR(210, 180, 140);
float
half_fov = player.fov / 2,
rel_x = player.x * width_ratio, rel_y = player.y * height_ratio;
float screen_x = 0, step_x = (screen_width / player.fov) * theta_step;
for (float theta = player.angle - half_fov; theta < player.angle + half_fov; theta += theta_step) {
float rad_theta = to_radians(theta);
float cos_theta = cos(rad_theta), sin_theta = sin(rad_theta);
float dist = 0;
while (dist += dist_step) {
float
new_x = cos_theta * dist + rel_x,
new_y = sin_theta * dist + rel_y;
if (map[(int) (new_y / height_ratio)][(int) (new_x / width_ratio)]) {
dist *= cos(to_radians(theta - player.angle));
float double_dist = 2 * dist;
if (double_dist >= screen_height) break;
SDL_Rect column = {screen_x, dist, step_x + 1, screen_height - double_dist};
SDL_RenderFillRect(renderer, &column);
SDL_RenderDrawRect(renderer, &column);
break;
}
}
screen_x += step_x;
}
}
void handle_input(const Uint8* keys, Player* player) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
exit(0);
}
else if (event.type == SDL_KEYDOWN) {
float radian_theta = to_radians(player -> angle);
float move_x = cos(radian_theta) * move_speed_decr,
move_y = sin(radian_theta) * move_speed_decr;
// handle arrow keys
if (keys[SDL_SCANCODE_UP]) player -> x += move_x, player -> y += move_y;
if (keys[SDL_SCANCODE_DOWN]) player -> x -= move_x, player -> y -= move_y;
if (keys[SDL_SCANCODE_LEFT]) player -> x += move_y, player -> y -= move_x;
if (keys[SDL_SCANCODE_RIGHT]) player -> x -= move_y, player -> y += move_x;
// handle 'a' and 's' for angle changes
if (keys[SDL_SCANCODE_A]) player -> angle -= angle_turn;
if (keys[SDL_SCANCODE_S]) player -> angle += angle_turn;
// safeguards for invalid positions and angles
if (player -> x < 0) player -> x = 0;
else if (player -> x > screen_width) player -> x = screen_width;
if (player -> y < 0) player -> y = 0;
else if (player -> y > screen_height) player -> y = screen_height;
// move the player to their previous coordinate if they're in a wall
if (map[(int) player -> y][(int) player -> x])
player -> y = player -> prev_y, player -> x = player -> prev_x;
if (player -> angle > 360) player -> angle = 0;
else if (player -> angle < 0) player -> angle = 360;
player -> prev_y = player -> y, player -> prev_x = player -> x;
}
}
}
int main() {
SDL_CreateWindowAndRenderer(screen_width, screen_height, 0, &window, &renderer);
SDL_SetWindowTitle(window, "Raycaster");
Player player = {5, 5, 0, 0, 0, 60};
SDL_Rect the_ceiling = {0, 0, screen_width, screen_height / 2};
SDL_Rect the_floor = {0, screen_height / 2, screen_width, screen_height};
const Uint8* keys = SDL_GetKeyboardState(NULL);
while (1) {
handle_input(keys, &player);
draw_rectangle(the_ceiling, 96, 96, 96);
draw_rectangle(the_floor, 255,69,0);
raycast(player);
SDL_RenderPresent(renderer);
SDL_UpdateWindowSurface(window);
}
}
You need to apply following diff:
diff --git a/so33.c b/so33.c
index e65cff8..b0f6d8a 100644
--- a/so33.c
+++ b/so33.c
## -56,7 +56,7 ## void raycast(Player player) {
float
half_fov = player.fov / 2,
- rel_x = player.x * width_ratio, rel_y = player.y * height_ratio;
+ rel_x = player.x, rel_y = player.y;
float screen_x = 0, step_x = (screen_width / player.fov) * theta_step;
## -70,12 +70,12 ## void raycast(Player player) {
new_x = cos_theta * dist + rel_x,
new_y = sin_theta * dist + rel_y;
- if (map[(int) (new_y / height_ratio)][(int) (new_x / width_ratio)]) {
+ if (map[(int) (new_y)][(int) (new_x)]) {
dist *= cos(to_radians(theta - player.angle));
- float double_dist = 2 * dist;
-
- if (double_dist >= screen_height) break;
- SDL_Rect column = {screen_x, dist, step_x + 1, screen_height - double_dist};
+ float wall_height = screen_height / dist;
+ if (wall_height > screen_height)
+ wall_height = screen_height;
+ SDL_Rect column = {screen_x, screen_height/2 - wall_height/2, step_x + 1, wall_height};
SDL_RenderFillRect(renderer, &column);
SDL_RenderDrawRect(renderer, &column);
A few issues were identified.
Coefficients width_ratio and height_ratio seems to mix coordinates in the map space with coordinates in the screen space. It is pointless. Moreover, it breaks navigation by moving faster along specific axis.
After projecting dist to the ray cast through the center of the screen (dist *= cos(...) you have to apply simple perspective to compute height of the wall (variable wall_height)
Finally, draw a rectangle of height wall_height around the middle horizontal line.
Edit. Set
dist_step = 0.01
There are two major problem in this code. The distance to the wall must be calculated for the intersection point of your ray to the wall instead of just relying that your endpoint lies inside the wall square.
Having a camera at C, the distortion is solved by casting rays from C through a sufficient number of points between A and B, just dividing this plane (your screen) to equally wide columns (pixels).
I'm fairly pessimistic about the cosine correction, since what I can tell, one should more likely adjust the drawn column width or position with it, than the column height.

How do I fix the warped perspective in my raycaster?

I am writing a raycaster using SDL's C API. I have spent weeks trying to fix the notorious fisheye effect to no avail. According to this source, I can multiply my calculated distance by the cosine of half of the FOV to fix it. That has not worked for me. I still have the cosine correction in my code nonetheless.
Here are two images demonstrating the distortion:
I think a core problem of my code may be that my angle increment is constant, while the increment should be smaller as I'm closer to the screen borders. Unfortunately, I don't know how to start implementing this.
If possible, could anyone please take a look at my code and give me a tip on how to remove the fisheye? To move in any direction, use the arrow keys. Use the 'a' and 's' keys to turn left and right respectively.
This is how I'm compiling: clang `pkg-config --cflags --libs sdl2` raycaster.c
#include <SDL2/SDL.h>
#include <math.h>
typedef struct {
float x, y, prev_x, prev_y, angle, fov;
} Player;
enum {
map_width = 12, map_height = 15,
screen_width = 800, screen_height = 500
};
const float
move_speed_decr = 0.08,
angle_turn = 2.0,
ray_theta_step = 0.4,
ray_dist_step = 0.8,
darkening = 1.8,
width_ratio = (float) screen_width / map_width,
height_ratio = (float) screen_height / map_height;
const unsigned char map[map_height][map_width] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1},
{1, 0, 4, 3, 2, 0, 0, 0, 2, 0, 0, 1},
{1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 1},
{1, 0, 0, 0, 4, 3, 2, 1, 4, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
SDL_Window* window;
SDL_Renderer* renderer;
float to_radians(float degrees) {
return degrees * M_PI / 180;
}
float distance(float x0, float y0, float x1, float y1) {
return sqrt(((x1 - x0) * (x1 - x0)) + ((y1 - y0) * (y1 - y0)));
}
void shade(int* color, int darkener) {
int darkened = *color - darkener;
*color = darkened < 0 ? 0 : darkened;
}
void draw_rectangle(SDL_Rect rectangle, int r, int g, int b) {
SDL_SetRenderDrawColor(renderer, r, g, b, SDL_ALPHA_OPAQUE);
SDL_RenderFillRect(renderer, &rectangle);
SDL_RenderDrawRect(renderer, &rectangle);
}
void raycast(Player player) {
float relative_x = player.x * width_ratio;
float relative_y = player.y * height_ratio;
float half_fov = player.fov / 2;
float width_fov_ratio = (screen_width / player.fov) / 2;
float distort_adjust = cos(to_radians(half_fov));
// the core of my problem may be in the constant increment of my angle
for (float theta = player.angle - half_fov, screen_x = 0;
theta < player.angle + half_fov;
theta += ray_theta_step, screen_x += width_fov_ratio) {
float radian_theta = to_radians(theta);
float cos_theta = cos(radian_theta), sin_theta = sin(radian_theta);
float d = 0, new_x, new_y;
while (d += ray_dist_step) {
new_x = cos_theta * d + relative_x;
new_y = sin_theta * d + relative_y;
int map_x = new_x / width_ratio, map_y = new_y / height_ratio;
int map_point = map[map_y][map_x];
if (map_point) {
int dist_wall = distance(relative_x, relative_y, new_x, new_y) * distort_adjust;
int twice_dist_wall = 2 * dist_wall;
if (twice_dist_wall >= screen_height) break;
else if (map_point) { // succeeds when a wall is present
int r, g, b;
switch (map_point) {
case 1: r = 255, g = 255, b = 0; break;
case 2: r = 0, g = 128, b = 128; break;
case 3: r = 255, g = 165, b = 0; break;
case 4: r = 255, g = 0, b = 0; break;
}
int color_decr = dist_wall / darkening;
shade(&r, color_decr);
shade(&g, color_decr);
shade(&b, color_decr);
SDL_Rect vertical_line = {
screen_x, dist_wall,
width_fov_ratio + 1,
screen_height - twice_dist_wall
};
draw_rectangle(vertical_line, r, g, b);
break;
}
}
}
}
}
void handle_input(const Uint8* keys, Player* player) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
exit(0);
}
else if (event.type == SDL_KEYDOWN) {
float radian_theta = to_radians(player -> angle);
float move_x = cos(radian_theta) * move_speed_decr,
move_y = sin(radian_theta) * move_speed_decr;
// handle arrow keys
if (keys[SDL_SCANCODE_UP]) player -> x += move_x, player -> y += move_y;
if (keys[SDL_SCANCODE_DOWN]) player -> x -= move_x, player -> y -= move_y;
if (keys[SDL_SCANCODE_LEFT]) player -> x += move_y, player -> y -= move_x;
if (keys[SDL_SCANCODE_RIGHT]) player -> x -= move_y, player -> y += move_x;
// handle 'a' and 's' for angle changes
if (keys[SDL_SCANCODE_A]) player -> angle -= angle_turn;
if (keys[SDL_SCANCODE_S]) player -> angle += angle_turn;
// safeguards for invalid positions and angles
if (player -> x < 0) player -> x = 0;
else if (player -> x > screen_width) player -> x = screen_width;
if (player -> y < 0) player -> y = 0;
else if (player -> y > screen_height) player -> y = screen_height;
// move the player to their previous coordinate if they're in a wall
if (map[(int) player -> y][(int) player -> x])
player -> y = player -> prev_y, player -> x = player -> prev_x;
if (player -> angle > 360) player -> angle = 0;
else if (player -> angle < 0) player -> angle = 360;
player -> prev_y = player -> y, player -> prev_x = player -> x;
}
}
}
int main() {
SDL_CreateWindowAndRenderer(screen_width, screen_height, 0, &window, &renderer);
SDL_SetWindowTitle(window, "Raycaster");
Player player = {5, 5, 0, 0, 0, 60};
SDL_Rect the_ceiling = {0, 0, screen_width, screen_height / 2};
SDL_Rect the_floor = {0, screen_height / 2, screen_width, screen_height};
const Uint8* keys = SDL_GetKeyboardState(NULL);
while (1) {
handle_input(keys, &player);
draw_rectangle(the_ceiling, 96, 96, 96);
draw_rectangle(the_floor, 210, 180, 140);
raycast(player);
SDL_RenderPresent(renderer);
SDL_UpdateWindowSurface(window);
}
}
After help from RandomDavis, the distortion is lessened. Here is the new result. Nonetheless, some warping remains:
NOTE:
To anyone who is still struggling with this problem, I solved it here:
How do I fix warped walls in my raycaster?
Okay I found a guide which talks about this exact issue.
Before drawing the wall, there is one problem that must be taken care of. This problem is known as the "fishbowl effect." Fishbowl effect happens because ray-casting implementation mixes polar coordinate and Cartesian coordinate together. Therefore, using the above formula on wall slices that are not directly in front of the viewer will gives a longer distance. This is not what we want because it will cause a viewing distortion such as illustrated below.
Thus to remove the viewing distortion, the resulting distance obtained from equations in Figure 17 must be multiplied by cos(BETA); where BETA is the angle of the ray that is being cast relative to the viewing angle. On the figure above, the viewing angle (ALPHA) is 90 degrees because the player is facing straight upward. Because we have 60 degrees field of view, BETA is 30 degrees for the leftmost ray and it is -30 degrees for the rightmost ray.

Matlab: arrayfun, two matrices X,Y as components of the vector

Suppose that X, Y are the matrices of coordinates inside the given intervals
xc = 0, yc = 0
xl = linspace(xc - 10, xc + 10, 2);
yl = linspace(yc - 10, yc + 10, 2);
[X,Y] = meshgrid(xl,yl);
and fun is a handle to some function test(v)
fun = #(v)test(v);
How to combine both matrices X, Y so that they represent components x,y of the vector v
res = arrayfun(fun, [X,Y]); //First processed X and then Y
Unfortunately, this solution does not work....
There is another way when the function is modified so that two parameters x, y are passed
fun = #(x, y)test(x, y);
res = arrayfun(fun, X, Y); //This works well
However, I would like to preserve an intertace of the function if any solution exists.
Thanks for your help.
Redefine fun as fun = #(x, y)test([x,y]);
No need to modify function test()
xc = 0;
yc = 0;
xl = linspace(xc - 10, xc + 10, 2);
yl = linspace(yc - 10, yc + 10, 2);
[X,Y] = meshgrid(xl,yl);
% Given function test
test =#(v)v(1) + v(2);
% pass x, y as a vector
fun = #(x, y)test([x,y]);
res = arrayfun(fun, X, Y);
% X =
-10 10
-10 10
% Y =
-10 -10
10 10
% fun(x, y) = x + y
% res =
-20 0
0 20
From Matlab doc:
B = arrayfun(func,A) applies the function func to the elements of A, one element at a time
B = arrayfun(func,A1,...,An) applies func to the elements of the arrays A1,...,An, so that B(i) = func(A1(i),...,An(i))
So you are using arrayfun in the wrong way.
Use a for loop or two nested loops instead.
for i=1:size(X,1)
for j=1:size(X,2)
res(i,j)=fun([X(i,j),Y(i,j)])
end
end
What are you trying to do?
Also, in Matlab, you should use % instead of // for commenting
These are some related questions:
arrayfun when each row of the array is an input
Passing a vector as multiple inputs to a function

MATLAB - Assignment has fewer non-singleton rhs dimensions than non-singleton subscripts

I set up an array like this.
img = % A GRAY-SCALE IMAGE
r = 20;
corners = randi( [1080, 1020], 100, 2);
d = r * 2 + 1;
squares = zeros(size(corners, 1), d, d);
w = corners(:, 1);
h = corners(:, 2);
for i = 1:size(corners, 1)
sq = img(max(w(i) - r, 0) : min(w(i) + r, size(img, 1)), ...
max(h(i) - r, 0) : min(h(i) + r, size(img, 2)));
squares(i, :, :) = (sq - mean(sq(:))) / std(sq(:));
end
When I try to run this code, I get an error message saying "Assignment has fewer non-singleton rhs dimensions than non-singleton subscripts". I'm not sure what this means because when I print out size(squares(i, :, :)) and size(sq) I get 1 41 41 and 41 41 respectively. I'm not sure what's wrong or how to fix it. Help?

Resources