Find right scale to draw an iteration of L-system - graphics

I made an OCaml program which draws on a Graphics window the representation of a given l-system using his definition,his commands interpretation and iteration.
The drawing is made using Turtle graphics(the turtle can draw a line,move to a given point and turn for a given angle).
The problem I have is that all the lines have the same size(and this is how it needs to be) and when I draw an L-system if i don't give the right line size the drawing goes out of graphics window as you can see on that picture.
I know I can move the drawing on the left but I always start drawing from the center of the window.What I need help for is how to set the right line size for a given sequence of cammands for example:
I have that list of instructions below :
ACAABAABABACACAACACACACAACAABABACAABAABABACACAACACACACAACAABABACAABAABABACACAACACACACAACAABABACAABAABABACACAACACACACAACAABA.
where A means: Draw a line of "X" size
B : turn π/2
C: turn -π/2.
How can I find the best value for X (size of the line) in order to have a drawing that stays on the graphics window.
The only solution I've found is to start from a given value (Example X=20) and try to draw the l-system with this value, if it goes out then try again with X/2 until it works !
Does anybody have a better idea?

You could do some analysis of the L-system to determine its range, and scale appropriately. However, this is not much different than just drawing it with an arbitrary size (say, 1) seeing how big it is, and scaling (once) to fit the screen (not just X/2 until works). For example, if you draw it with scale=1 and it is 40 units in size, and your screen is 400 units, you know you can draw with scale=10 and still fit. You can also use this first pass to determine XY offset so you can center it.

My idea is to make one pass to evaluate sizes of your labyrinth. Let (W: int) be your width variable. When painter moves West you decrement W and when your painter moves East you incerement W. If m1 is maximal possible value of W and m2 is minimal value (maybe, < 0) of W during process then total width of you diagram is padding + linewidth * (m1-m2)
For example: let's painter initially looks to East.
AAAAABABAAAAAABABA
i.e.
<<<<<.
>.>>>>
During process W will change this way:
AAAAABABAAAAA A B A BA
01234555543210-1-1-1-10
Robot makes 5 steps to East, moves up, and moves 6 steps on West, moves down and returns to start location. In this case m1 = 5 and m2 = -1 and you need canvas of size 5+(-1) multiply line width.

Related

Change perspective in POV-Ray? (less convergence)

Can you change the perspective in POV-Ray, so that convergence between parallel lines does not look so steep?
E.g. change this angle (the convergence of the checkered floor into the distance) here
To an angle like this
I want it to seem like you're looking at something nearby, so with a smaller angle of convergence in parallel lines.
To illustrate it more: instead of a view like this
Use a view like this
Move the camera backwards and zoom in (by making the angle smaller):
camera {
perspective
location <0,0,-15> // move this backwards
sky y
up y
angle 30 // make this smaller
right (image_width/image_height)*x
look_at <0,0,0>
}
You can go to the extreme by using an orthographic "camera":
camera {
orthographic
location <0,0,-15> // Move backwards, no matter how far
sky y
up y * h // where h = hight you want to cover
right x * w // where w = width you want to cover
look_at <0,0,0>
}
The other extreme is the fish-eye lens.
You need to reduce the field of view of your camera's view frustum. The larger the field of view, the more stuff you're trying to squeeze into the output of your camera's render and so they parallel lines will converge faster. So in your first example with a cube, the camera will be more focused on the cube and the areas just immediately around it, than the whole environment.
The other option is to make your far plane much closer to your near plane, so you don't see many things that are far off. So in you first image example, you'll only see the first four or five grids instead.

why different Mandelbrot zooming values yields same results?

what gives one the ability to define how deep the zooming process would be?
what i mean is that i tried earlier to run mandelbrot set with 200 iteration and then compared the results with a 1000 iterations run. the results were kinda surprising because i got the same zooming level.the iterations were constant the entire process and the mandelbrot set was defined with 512X512 pixels constant. what should i change in order to get a deeper zooming level?
thanks!
edit : i would also like to mention that from nice looking picture, after i get to the 2nd-3rd level of mandelbrot the entire set is viewed as a giant pixel. why is that?
2d edit : after an extensive research i've just noticed that what makes the entire set to look like a big pixel is because all points get same iterations count,in my case they are all 60...
This may be too abstract, or too concrete, or incomprehensible. Like I said in the comment, it would be easier to discuss with your code at hand.
If you mean what I think you mean by zooming, you'd change the boundaries of c (in the formula z[n+1] = z[n]^2 + c).
To explain, the full Mandelbrot set is contained within a circle with radius 2 around a center [0;0]. The c in the formula is a complex number, i.e. [r;i] (real;imaginary), which, on the computer screen, corresponds to x and y.
In other words, if we place that radius 2 circle so that it is exactly contained within our image, then [-2;2] will be the upper left corner of our image, and [2;-2] is the lower right corner.
We then take each point of our image, calculate what its pixel coordinates [x;y] correspond to in terms of the smaller, "actual" coordinate system [r;i]. Then we have our c and can send it through our iterations.
So, to "zoom", you'd pick other boundaries [r;i] than the full [-2;2],[2:-2], e.g. [-1;1],[1:-1].
With 512x512 pixels, and an "actual" coordinate system that's now 2 by 2, that would mean each pixel corresponds to 2/512 units of the "actual" coordinate system. So your first r value would be -1, the next would be -1 + 2/512 = -0.99609375 etc.
The number of iterations only decide how accurate your rendering will be. Generally, the further you "zoom" in, the more accurate they'll need to be, so the more iterations you'll need in order to capture the details.

How to draw a curve that goes both up and down?

I've used the following code to make 3 points, draw them to a bitmap, then draw the bitmap to the main form, however it seems to always draw point 3 before point 2, because the Y co-ordinate is lower then point 2's. Is there a way to get over this, as I need a curve that curves up and down, rather than just up
Bitmap bit = new Bitmap(490, 490);
Graphics g = Graphics.FromImage(bit);
Graphics form = this.CreateGraphics();
pntPoints[0] = this.pictureBox1.Location;
pntPoints[1] = new Point(100,300);
pntPoints[2] = new Point(200, 150);
g.DrawCurve(p, pntPoints);
form.DrawImage(bit, 0, 5);
bit.Dispose();
g.Dispose();
Y-coordinate for point 3 is not lower, it's actually higher. The (0;0) point of Graphics is in the left top corner, and the Y value increases from the top down rather than from the bottom up. So a point (0;100) will be higher than (0;200) on the result image.
If you want a curve that goes up then down, you should place your first point in (0; 489), your second point in (100, 190) and your third point in (200, 340).
I recommend you put in a debug function that will mark and identify the points themselves, so you can see exactly where they are. A pixel in an off color, the index of the point, and the coordinates together will help you identify what is going where.
Now, I'm wondering, are those two points really supposed to be absolute, or are they supposed to be relative to the first point?

Algorithm for Polygon Image Fill

I want an efficient algorithm to fill polygon with an Image, I want to fill an Image into Trapezoid. currently I am doing it in two steps
1) First Perform StretchBlt on Image,
2) Perform Column by Column vertical StretchBlt,
Is there any better method to implement this? Is there any Generic and Fast algorithm which can fill any polygon?
Thanks,
Sunny
I can't help you with the distortion part, but filling polygons is pretty simple, especially if they are convex.
For each Y scan line have a table indexed by Y, containing a minX and maxX.
For each edge, run a DDA line-drawing algorithm, and use it to fill in the table entries.
For each Y line, now you have a minX and maxX, so you can just fill that segment of the scan line.
The hard part is a mental trick - do not think of coordinates as specifying pixels. Think of coordinates as lying between the pixels. In other words, if you have a rectangle going from point 0,0 to point 2,2, it should light up 4 pixels, not 9. Most problems with polygon-filling revolve around this issue.
ADDED: OK, it sounds like what you're really asking is how to stretch the image to a non-rectangular shape (but trapezoidal). I would do it in terms of parameters s and t, going from 0 to 1. In other words, a location in the original rectangle is (x + w0*s, y + h0*t). Then define a function such that s and t also map to positions in the trapezoid, such as ((x+t*a) + w0*s*(t-1) + w1*s*t, y + h1*t). This defines a coordinate mapping between the two shapes. Then just scan x and y, converting to s and t, and mapping points from one to the other. You probably want to have a little smoothing filter rather than a direct copy.
ADDED to try to give a better explanation:
I'm supposing both your rectangle and trapezoid have top and bottom edges parallel with the X axis. The lower-left corner of the rectangle is <x0,y0>, and the lower-left corner of the trapezoid is <x1,y1>. I assume the rectangle's width and height are <w,h>.
For the trapezoid, I assume it has height h1, and that it's lower width is w0, while it's upper width is w1. I assume it's left edge "slants" by a distance a, so that the position of its upper-left corner is <x1+a, y1+h1>. Now suppose you iterate <x,y> over the rectangle. At each point, compute s = (x-x0)/w, and t = (y-y0)/h, which are both in the range 0 to 1. (I'll let you figure out how to do that without using floating point.) Then convert that to a coordinate in the trapezoid, as xt = ((x1 + t*a) + s*(w0*(1-t) + w1*t)), and yt = y1 + h1*t. Then <xt,yt> is the point in the trapezoid corresponding to <x,y> in the rectangle. Now I'll let you figure out how to do the copying :-) Good luck.
P.S. And please don't forget - coordinates fall between pixels, not on them.
Would it be feasible to sidestep the problem and use OpenGL to do this for you? OpenGL can render to memory contexts and if you can take advantage of any hardware acceleration by doing this that'll completely dwarf any code tweaks you can make on the CPU (although on some older cards memory context rendering may not be able to take advantage of the hardware).
If you want to do this completely in software MESA may be an option.

UI question: Designing for widescreen and 4:3 aspect ratios simultaneously?

I'm working on a UI which needs to work in different aspect ratios, 16:9, 16:10, 4:3
The idea is conceptually simple: Everything is centered to the screen in a rough 4:3 area and anything outside this portion of screen has basic artwork, so something like this:
(not drawn to scale)
Where the pink area represents whre all the UI objects are positioned and the blue area is just background and effects.
The trick is in usability, if I pass in coordinates (0,0) in a 4:3 aspect ratio environment (0,0) would be the top left of the screen. However if I'm in a 16:9 environment (0,0) needs to get renormalized based on the new aspect ratio for it to be in the appropriate place. So my question is: How can I achieve this?
edit: for clarification this is basically for a UI system and while I listed the ratios above as 4:3, 16:9, 16:10 it should be able to dynamically adjust values for whatever aspect ratio it is set to.
edit 2: Just to add more details to the situation: When the positions fo rsetting are passed in they are passed in as a % of the screens current widht height, so basically setting position x would be: [pos x as portion of screen]*SCREEN_WIDTH where screen width is the width of the current screen itself.
The obvious answer seems to be an offset. Since 4x3 is 16x9, it appears you want a 16x9 screen to have 2x9 bands to the left and the right. Hence, the X offset should be (2/16) * width.
For 16x10 screens, the factor is slightly more complicated: 4x3 is 13.33x10, so you have edges of width 1.67, and the X offset should be (1.67/16) * width = (5/48)* width.
So ... Can't you just come up with an abstraction layer, that hides the differences? One idea could be to model a "border" around the active area, that gets added. For 4:3 displays, set the border size to 0 to make the active area cover the full screen.

Resources