Best line equation to use for computational geometry - language-agnostic

I'm looking to write a little comp-geom library, in Ruby.
I'm about to write the code for lines, and was wondering which line equation I should use:
ax + by + c = 0
r + tv (where r and v are vectors)
Thanks.

If using the classical equations is not a requirement, I'd suggest an array of four co-ordinates: xStart, yStart, xEnd and yEnd.
In case you need to make the line position dynamic, you could use an array of two parameters: alpha and radius. The former represents radial rotation relative to the horizontal axis and the latter is the length of line.
Yet another option would be vectors in the form of (X;Y).
Samples in C:
int endpointsLine[4] = {0, 0, 30, 40};
double radialLine[2] = {5.35589, 50};
int vectorLine[2] = {30, 40};
The "endpoints" format is fully compatible with modern line-drawing algorithms, such as Xiaolin Wu's line algorithm and Bresenham's line algorithm but it represents specific screen co-ordinates which is not the case with "radial" and "vector" format.

Related

What is the most comprehensible way to create a Rect object from a center point and a size in PyGame?

I want to crate an pygame.Rect object from a center point (xc, yc) and a size (w, h).
pygame.Rect just provides a constructor with the top left point and the size.
Of course I can calculate the top left point:
rect = pygame.Rect(xc - w // 2, yc - h // 2, w, h)
Or I can set the location via the virtual attribute center:
rect = pygame.Rect(0, 0, w, h)
rect.center = xc, yc
If I want to completely confuse someone, I use inflate:
rect = pygame.Rect(xc, yc, 0, 0).inflate(w, h)
Or even clamp:
rect = pygame.Rect(0, 0, w, h).clamp((xc, yc, 0, 0))
Not any of this methods satisfies me. Either I have to calculate something, I have to write several lines of code, or I have to use a function that completely hides what is happening.
I also don't want to write a function (or lambda) as I think this is completely over the top for creating a simple rectangle.
So my question is:
How do you usually create such a rectangle with a self-explanatory line of code so everyone can see what is happening at a glance?
Is there a much easier method? Do I miss something?
Interesting question Rabbid76.
I personally try to write code such that a person with only a general understanding of programming concepts can read the code. This includes absolute beginners (95% of people making PyGame questions), and converts from other languages.
This is why I mostly shy-away from using Python's if x < y < z:, and blah = [ x for x in some-complex-iff-loop ], et.al. syntax. (And that's also why I always put my if conditions in brackets.) Sure if you know python well it doesn't matter, but for an example of why it's important, go try to read a Perl script from the mid 2010's and you see stuff like:
print #$_, "\n" foreach ( #tgs );
It didn't have to be written like that, they could have used a loop-block with some instructive variable names, and not $_, etc.
So bearing the above in mind, the question comes down to - Which is the easiest to read and understand.
So for my 2-cents worth, it has to be option #2:
rect = pygame.Rect(0, 0, w, h)
rect.center = xc, yc
It's absolutely clear to a syntax-ignorant code reader that a rectangle is being created, and some kind of centre-point is being set.
But to make the code more "self documenting", it could be wrapped in a function call:
def getRectAround( centre_point, width, height ):
""" Return a pygame.Rect of size width by height,
centred around the given centre_point """
rectangle = pygame.Rect( 0, 0, w, h ) # make new rectangle
rectangle.center = centre_point # centre rectangle
return rectangle
# ...
rect = getRectAround( ( x, y ), w, h )
Sometimes more code is better.

Does a programming language with the following features exist?

Is there a language which will support the following concept or is there a pattern to achieve something similar with existing one?
Concept
I want to define a Rectangle with the following properties: Length, Height, Area, Perimeter; where Area = Length * Height and Perimeter = (2 * Length) + (2 * Height).
Given the statement above, if I want to create a Rectangle by giving it a Length and a Height, it should of course automatically fill out the rest of the properties.
However, it should go further and automatically allow you to create a Rectangle with any two properties (say Height and Perimeter) because that is also mathematically enough to create the same Rectangle.
Example
To help explain the idea, take this example:
//Declaration
Rectangle
{
Height, Length, Area, Perimeter;
Area = Height * Length;
Perimeter = (2 * Length) + (2 * Height);
}
//Usage
main()
{
var rectangleA = new Rectangle(Height, Length);
var rectangleB = new Rectangle(Height, Area);
Assert(rectangleA == rectangleB);
}
Notice how I didn't need to define constructors for Rectangle. Notice I did not need specify the specific logic needed if a Rectangle was created using Height and Area.
Edit: Should be rectangle and not a square for a proper example.
What you are looking for is a language with an integrated computer algebra system. It has to be able to resolve equations with respect to different variables.
While it would be possible to implement something like this, I doubt that it would make sense because in many cases there will be either no solution or multiple solutions.
Even your simple example will not work if only area and perimeter are given because there will usually be two solutions. (I assume that your class actually represents a rectangle and not a square, otherwise you should not have separate variables for length and height.)
Example:
Input: area = 2, perimeter = 6
Solution 1: length = 2, height = 1
Solution 2: length = 1, height = 2
Another remark not really related to your question: Your class obviously contains redundant member variables. This is a bad thing for various reasons, the most important being the possibility of inconsistencies. Unless you have very strict performance constraints, you should store only two of them, say length and width, and provide methods to calculate the others when needed.
Of course such a language exists. Many do, as you've now pointed out in your own comment to this answer.
In the example below I'll be using the Powerloom representation system, implemented in a language called STELLA.
You can play with it from within a Common Lisp environment.
Once you have everything installed you can load the language by running:
(cl:load "load-powerloom.lisp")
(in-package "STELLA")
(in-dialect "KIF")
That's about all you need to start building awesome geometrical objects.
Within STELLA you may define a concept with the primitive defconcept:
(defconcept Rectangle (?r)
:documentation "Curious geometrical objects that live on a plane.")
And define its properties with deffunction:
(deffunction rect-height ((?t Rectangle)) :-> (?n INTEGER))
(deffunction rect-length ((?t Rectangle)) :-> (?n INTEGER))
(deffunction area ((?t Rectangle)) :-> (?n INTEGER))
(deffunction perimeter ((?t Rectangle)) :-> (?n INTEGER))
To make the relations between area, perimeter and the sides of your rectangle, you'll have to make some assertions. That's what you'll have assert for.
(assert (forall (?t Rectangle)
(= (area ?t) (* (rect-height ?t) (rect-length ?t)))))
(assert (forall (?t Rectangle)
(= (perimeter ?t) (+ (* 2 (rect-height ?t))
(* 2 (rect-length ?t))))))
You are telling STELLA that for all rectangles, the area is the product of height and length, and that for all rectangles, the perimeter is twice the height plus twice the length.
Now you can instantiate your objects, and it doesn't matter what properties you give it, as long as they make sense.
(definstance rect1 :Rectangle true :rect-height 10 :rect-length 10)
(definstance rect2 :Rectangle true :area 40 :rect-height 20)
Here you instantiate rect1 with height and length as parameters, and rect2 with area and height.
But its always good to check that the language is doing what you expect:
STELLA> (retrieve all ?x (= (area rect1) ?x))
There is 1 solution:
#1: ?X=100
STELLA> (retrieve all ?x (= (rect-length rect2) ?x))
There is 1 solution:
#1: ?X=2
If you ever get tired of rectangles and decide to build a beautiful square, why not derive a concept?
(defconcept Square ((?r Rectangle))
:documentation "Weird rectangles that fascinated the Greeks"
:<=> (= (rect-height ?r) (rect-length ?r)))
Simply tell STELLA that squares are rectangles where height and length are equal.
Now try it out:
STELLA> (definstance nice-rectangle :Rectangle true :rect-length 10 :area 100)
|i|NICE-RECTANGLE
STELLA> (ask (Square nice-rectangle))
TRUE
I'm not an expert at all, but I find the language fascinating. It's sad that there is so little information about it on the internet. Even the manual is incomplete.
For more information I'd suggest starting with these slides.
The famous book SICP teaches how to build a nondeterministic evaluator for such a language here.
And finally, a wonderful write up describing motivations and applications behind these ideas can be seen here.
In C#, you can use properties, which have implicit getters and setters. That way you can write something like:
public class Square {
public int Length {
get { return length; }
set { length = value; }
}
public int Area {
get { return length * length; }
set { length = Math.Sqrt(value); }
}
public int Perimeter {
get { return length * 4; }
set { length = value / 4; }
}
private int length;
}
Now you can write:
Square square = new Square();
square.Length = 2;
Console.WriteLine(square.Length); // "2"
Console.WriteLine(square.Area); // "4"
Console.WriteLine(square.Perimeter); // "8"
square.Area = 9;
Console.WriteLine(square.Length); // "3"
Console.WriteLine(square.Area); // "9"
Console.WriteLine(square.Perimeter); // "12"
Edit:
C# also allows you name properties at your choosing when instantiating an object:
Square square1 = new Square { Perimeter = 12 };
Square square2 = new Square { Length = 4 };
I don't think something like this does exist in the form of a programming language.
Ontology
However the first approach I can think about is defining an Ontology, I mean a set of rules about
Entities: Rectangle, Square, Dog, Car, etc...
Attributes: Area, Height, Number of Wheels, etc...
Relations between (1) and (2): Rectangle's Area is Height * Width, ...
Now given a list of attributes and the required output Entity
I have height and width and I need a Rectangle
the system could search for a path through the rules graph to produce the required outcome based on the provided inputs.
Real world example
Wolfram Alpha probably follows the technique described above

Explanation of a Hough accumulator that does not match image

I was having fun with image processing and hough transforms on Octave but the results are not the expected ones.
Here is my edges image:
and here is my hough accumulator (x-axis is angle in deg, y-axis is radius):
I feel like I am missing the horizontal streaks but there is no local maximum in the accumulator for the 0/180 angle values.
Also, for the vertical streaks, the value of the radius should be equal to the x value of the edge's image, but instead the values of r are very high:
exp: the first vertical line on the left of the image has an equation of x=20(approx) -> r.r = x.x + y.y -> r=x -> r=20
The overall resulting lines detected do not match the edges at all:
Acculmulator with detected maxima:
Resulting lines:
As you can see the maximas of the accumulator are satisfyingly detected but the resulting lines' radius values are too high and theta values are missing.
It almost looks like the hough transform accumulator does not correspond to the image...
Can someone help me figure out why and how to correct it?
Here is my code:
function [r, theta] = findScratches (img, edge)
hough = houghtf(edge,"line", pi*[0:360]/180);
threshHough = hough>.5*max(hough(:));
[r, theta] = find(threshHough>0);
%deg to rad for the trig functions
theta = theta/180*pi;
%according to octave doc r range is 2*diagonal
%-> bring it down to 1*diagonal or all lines are out of the picture
r = r/2;
%coefficients of the line y=ax+b
a = -cos(theta)./sin(theta);
b = r./sin(theta);
x = 1:size(img,2);
y = a * x + b;
figure(1)
imagesc(edge);
colormap gray;
hold on;
for i=1:size(y,1)
axis ij;
plot(y(i,:),x,'r','linewidth',1);
end
hold off;
endfunction
Thank you in advance.
You're definitely on the right track. Blurring the accumulator image would help before looking for the hotspots. Also, why not do a quick erode and dilate before doing the hough transform?
I had the same issue - detected lines had the correct slope but were shifted. The problem is that the r returned by the find(threshHough>0) function call is in the interval of [0,2*diag] while the Hough transform operates with values of r from the interval of [-diag,diag]. Therefore if you change the line
r=r/2
to
r=r-size(hough,1)/2
you will get the correct offset.
Lets define a vector of angles (in radians):
angles=pi*[0:360]/180
You should not take this operation: theta = theta/180*pi.
Replace it by: theta = angles(theta), where theta are indices
Some one commented above suggesting adjusting r to -diag to +diag range by
r=r-size(hough,1)/2
This worked well for me. However another difference was that I used the default angle to compute Hough Transform with angles -90 to +90. The theta range in the vector is +1 to +181. So It needs to be adjusted by -91, then convert to radian.
theta = (theta-91)*pi/180;
With above 2 changes, rest of the code works ok.

SciLab Plotting

How would you plot these in SciLab or MatLab? I am new to these and have no idea how the software works. Please help.
$Plot following functions with different colors in Scilab or MatLab
– f2(x) = logn
– f3(x) = n
– f4(x) = nlogn
– f5(x) = n2
– f6(x) = nj (j > 2)
– f7(x) = cn (c > 1)
– f8(x) = n!
where x = linspace(1, 50, 50).
Well, a lot of these are built-in functions. For example
>> x = linspace(1,50,50);
>> plot(x,log(x))
>> plot(x,x)
>> plot(x,x.*log(x))
>> plot(x,x.^2)
I don't know what nj (j > 2) and cn (c > 1) are supposed to mean.
For the last one, you should look at the function factorial.
It's not clear from the context whether you're supposed to plot them on different graphs or all on the same graph. If all on the same graph, then you can use
>> hold on;
to freeze the current axes - that means that any new lines will get drawn on top of the old ones, instead of being drawn on a fresh set of axes.
In Matlab (and probably in Scilab) you can supply a "line spec" argument to the plot function, which tells it what color and style to draw the line in. For example,
>> figure
>> hold on
>> plot(x,log(x),'b')
>> plot(x,x/10,'r')
>> plot(x,x.^2/1000,'g')
Tells Matlab to plot the function f(x)=log(x) in blue, f(x)=x/10 in red and f(x)=x^2/1000 in green, which results in this plot:
I can't comment or upvote yet but I'd add to Chris Taylor's answer that in Scilab the hold on and hold off convention isn't used. All plot commands output to the current axes, which are 'held on' all the time. If you want to generate a new figure or change the current axes you can use figure(n), where n can be any (nonconsecutive) positive integer - just a label really.
See also clf(n), gcf() and gca() - Scilab's figure handling differs quite a bit from Matlab's, though the matplotlib ATOMS module goes some way towards making Scilab look and behave more like Matlab.
In Scilab, it will be
x = 1:50;
clf
plot("ll", x,log, x,x, x,x.*log(x), x,x.^2)
gca().sub_ticks(2) = 8;
xgrid(color("grey"))
legend("$"+["ln(x)", "x", "x.ln(x)", "x^2"]+"$", "in_upper_left")

Understanding texture's linear filtering in cuda

according to the CUDA programming guide, the value returned by the texture fetch is
tex(x) = (1-a)T[i] + aT[i+1] for a one-dimensional texture
where i = floor(Xb), a = frac(Xb), Xb=x-0.5
Suppose we have a one dimensional texture that only has two texals. For example:
T[0] = 0.2, T[1] = 1.5
Say we want to fetch the texal at 1, which I think should return T[1] which is 1.5.
However, if you follow the rule given in the programming guide, the return value will be:
Xb = 1 - 0.5 = 0.5
a = 0.5
i = 0
return value = 0.5*T[0] + 0.5*T[1] = 0.85
which does not make any sense to me. Can someone explain why the linear filtering is done in such way by CUDA? Thanks
The linear filtering algorithm in CUDA assumes texel values are located at the centroid of the interpolation volume (so voxel centered, if you like). In your 1D filtering example, the input data is implicitly taken as
T[0]=(0.5, 0.2) T[1]=(1.5, 1.5)
So your example is asking for Tex(1), which is the midpoint between the two texel values, ie.
0.5*0.2 + 0.5*1.5 = 0.85
To get T[1] returned you would require Tex(1.5) and that is the general rule - add 0.5 to coordinates if you want to treat the texture data as being at the voxel vertices, rather than the voxel center.