Extracting a tuple in a tuple of tuples Haskell - haskell

I have to make a program, which decides if two circles are overlapping in haskell.
I have the following things defined:
-- | A 2D Point.
type Point = (Float,Float)
-- | A Circle is a pair of its center point and its radius.
type Circle = (Point,Float)
I need to make a distance function which calculates the distance between two points (hence the centeres of the 2 circles) and then a function which decides if they are overlapping by checking that the distance between the two centeres is smaller than the sum of the radiuses(or radii)
The problem is the centres are a touple and the radius is a single element
heres the function i made for distance:
-- | Distance between two points.
distance :: Point -> Point -> Float
distance p1 p2 = ((snd p1 - fst p1)^2 + (snd p2 - snd p1)^2)^(1/2)
and now i need to do distance < 2 * radius but i cant combine them because the distance should be performed on a touple and the radius on a single element
heres what i tried :
-- | 'True' if the given circles overlap, else 'False'.
overlap :: Circle -> Circle -> Bool
overlap c1 c2 = [distance x,y | x<-(x,y):c1, y<-(x1,y1):c2] < [sum z,z1 | z<-(z):c1, z1<-(z1):c2]
but of course it doesnt work :(
the test code that should prove my function is
-- | Some example calls to try out the 'overlap' function.
main :: IO ()
main = do
let circle1 = ((0,0),1)
circle2 = ((5,6),1)
circle3 = ((2,3),14)
print "overlap circle1 circle2:"
print (overlap circle1 circle2)
print "overlap circle1 circle3:"
print (overlap circle1 circle3)
print "overlap circle3 circle2:"
print (overlap circle3 circle2)

You have actually already solved your own problem, you just don't know it yet!
a function which decides if they are overlapping by checking that the distance between the two centeres is smaller than the sum of the radiuses(or radii)
I'll translate this sentence directly to Haskell:
a function which decides if they are overlapping
| by checking that the distance
| | between the two centres
| | | | is smaller than
| | | | | the sum of
| | | | | |
| | | | | the radiuses
| | | | | | | |
v v v v v v v v
overlap c1 c2 = distance (centre c1) (centre c2) < radius c1 + radius c2
To make this work, we need to define the two functions centre and radius, which get the centre point and the radius of a circle respectively.
centre c = fst c
radius c = snd c
It's as simple as that!

Related

Histogram bars with different bar colors

I would like to get a histogram with alternating gradients of a given color, according to decile breakpoints, as shown in figure below:
Example data:
clear
input float dn3001 double hw0010
1219000 2823.89408574376
-16390 520.112200750285
121010 238.732322261911
953839 221.316063150235
465000 247.280750487467
-870 280.305382323347
96000 2946.16661611018
69500 355.33497718705
113000 1421.43087298696
30500 616.914514202173
20000 3389.34765405599
154000 305.674687642557
440500 525.694777777734
56870 1823.24691219821
330500 376.651172915574
101000 465.098273950744
401046.5 660.816203440777
31872 1693.02190101773
220345 603.326244510505
193360 677.527413164373
196300 568.436679602066
222640 427.051692314575
510500 318.557431587468
131450 1388.72862441839
122300 532.996690473983
305 2441.72289873923
313500 292.610321722557
184500 2699.67735757755
1615564.6 386.944439319246
126528 3018.77523617479
711110 511.604491869939
127440 256.968118266053
424900 1620.366555701
95491 3097.46262561529
287500 413.119620218929
70050 2119.47171174278
75460 299.232446656805
210500 290.391474820414
135800 292.141670444933
119924 303.953183619671
81075 1568.41438245214
152 289.175871985445
73000 2551.12752046544
246500 327.474430367518
159960 2350.26463245568
14522 456.56909870547
139000 319.451311193507
68661 2771.34087931684
214089.7 388.589383036063
927800 849.088069585408
7840 1512.71702946577
140140 852.940547469624
21646.566 2405.47949923772
end
The code below produces a graph with uneven bar spread:
xtile aux = dn3001 [aw=hw0010], nq(10)
_pctile dn3001[aw=hw0010], nq(10)
sort dn3001
list dn3001 aux
return list
scalar p10=r(r1)
scalar p20=r(r2)
scalar p30=r(r3)
scalar p40=r(r4)
scalar p50=r(r5)
scalar p60=r(r6)
scalar p70=r(r7)
scalar p80=r(r8)
scalar p90=r(r9)
drop aux
sum dn3001 [aw=hw0010], d
scalar p1=r(p1)
scalar p95=r(p95)
twoway histogram dn3001 if dn3001>=scalar(p1) & dn3001<scalar(p10), bcolor(green%20) freq legend(off) ///
|| histogram dn3001 if dn3001>=scalar(p10) & dn3001<scalar(p20), bcolor(green) freq legend(off) ///
|| histogram dn3001 if dn3001>=scalar(p20) & dn3001<scalar(p30), bcolor(green%20) freq legend(off) ///
|| histogram dn3001 if dn3001>=scalar(p30) & dn3001<scalar(p40), bcolor(green) freq legend(off) ///
|| histogram dn3001 if dn3001>=scalar(p40) & dn3001<scalar(p50), bcolor(green%20) freq legend(off) ///
|| histogram dn3001 if dn3001>=scalar(p50) & dn3001<scalar(p60), bcolor(green) freq legend(off) ///
|| histogram dn3001 if dn3001>=scalar(p60) & dn3001<scalar(p70), bcolor(green%20) freq legend(off) ///
|| histogram dn3001 if dn3001>=scalar(p70) & dn3001<scalar(p80), bcolor(green) freq legend(off) ///
|| histogram dn3001 if dn3001>=scalar(p80) & dn3001<scalar(p90), bcolor(green%20) freq legend(off) ///
|| histogram dn3001 if dn3001>=scalar(p90) & dn3001<scalar(p95), bcolor(green) freq legend(off)
How can I get the same bar width?
Here is one potential approach:
twoway__histogram_gen dn3001, freq bin(50) generate(b a, replace)
_pctile dn3001 [aw=hw0010], nq(10)
return list
scalars:
r(r1) = 20000
r(r2) = 30500
r(r3) = 68661
r(r4) = 75460
r(r5) = 96000
r(r6) = 126528
r(r7) = 159960
r(r8) = 196300
r(r9) = 440500
generate group = .
forvalues i = 9(-1)1 {
replace group = `i' if a <= `r(r`i')'
}
replace group = 10 if a > `r(r9)' & _n <= 20
list a b group in 1 / 20, sepby(group)
+-----------------------+
| a b group |
|-----------------------|
1. | -70.45375 6 1 |
|-----------------------|
2. | 32568.64 4 3 |
3. | 65207.73 7 3 |
|-----------------------|
4. | 97846.82 4 6 |
|-----------------------|
5. | 130485.9 9 7 |
|-----------------------|
6. | 163125 2 8 |
7. | 195764.1 4 8 |
|-----------------------|
8. | 228403.2 3 9 |
9. | 261042.3 1 9 |
10. | 293681.4 1 9 |
11. | 326320.5 2 9 |
12. | 391598.7 1 9 |
13. | 424237.8 2 9 |
|-----------------------|
14. | 456876.8 1 10 |
15. | 522155 1 10 |
16. | 717989.6 1 10 |
17. | 913824.1 1 10 |
18. | 946463.3 1 10 |
19. | 1207576 1 10 |
20. | 1599245 1 10 |
+-----------------------+
Result:
twoway (bar b a, barwidth(25000) legend(off)) ///
(bar b a if group == 3, barwidth(25000) color(green)) ///
(bar b a if group == 9, barwidth(25000) color(red))
More a comment (or a series of comments) than an answer you seek, but the graph won't fit in a comment.
Your approach looks doomed -- if not to failure, then to extreme difficulty.
There is no guarantee whatsoever that any of your quantile bin limits will match any of the histogram bin limits.
Similarly, there is no guarantee that the difference between adjacent quantiles is a simple multiple of any histogram bin width you might choose. You might be tempted to fudge this by colouring a bar according to whichever quantile bin was more frequent, but that would be ignoring details. So suppose your histogram bar was for [100, 200) but some values in that interval belong to one quantile bin and some to another: what would you do? And what would you do if 3 or more quantile bins fell within a histogram bar?
By specifying multiple histograms without specifying starts or bin widths you are unleashing anarchy. Stata will make separate decisions for each histogram based partly on sample sizes. That's what your code is telling it to do, but not what you want.
Your histograms don't know anything about the analytic weights you used.
Beyond that, your question raises all sorts of unnecessary puzzles.
Why produce aux and do nothing with it? It's a point of standard art on SO to show the minimum code necessary to explain your problem.
You say you are interested in deciles but inconsistently are also working with 1 and 95% percentiles.
Why you have such irregular values with very different weights is unclear but inessential for your immediate question. But all that inclines me to think that you cannot get a histogram like your example graph easily or effectively from your data. You have just 53 data points and so weights make no difference to your being unable to have more than 53 non-empty bins.
How the bin limits fall relative to the data can be shown directly without a histogram.
With your example data (thanks!) I do this
xtile aux = dn3001 [aw=hw0010], nq(10)
quantile dn3001, ms(none) mla(aux) mlabpos(0) scheme(s1color) rlopts(lc(none))
I would use a logarithmic scale ordinarily but negative values rule that out.
Here I go beyond strict programming issues, but the question inevitably raises the issues I address.

spark dataframe sum of column based on condition

I want to calculate the portion of the value, with only two partitions( where type == red and where type != red)
ID | type | value
-----------------------------
1 | red | 10
2 | blue | 20
3 | yellow | 30
result should be :
ID | type | value | portion
-----------------------------
1 | red | 10 | 1
2 | blue | 20 |0.4
3 | yellow | 30 |0.6
The normal window function in spark only supports partitionby a whole column, but I need the "blue" and "yellow", together recognized as the "non-red" type.
Any idea?
First add a column is_red to easier differentiate between the two groups. Then you can groupBy this new column and get the sums for each of the two groups respectively.
To get the fraction (portion), simply divide each row's value by the correct sum, taking into account if the type is red or not. This part can be done using when and otherwise in Spark.
Below is the Scala code to do this. There is a sortBy since when using groupBy the order of results is not guaranteed. With the sort, sum1 below will contain the total sum for all non-red types while sum2 is the sum for red types.
val sum1 :: sum2 :: _ = df.withColumn("is_red", $"type" === lit("red"))
.groupBy($"is_red")
.agg(sum($"value"))
.collect()
.map(row => (row.getAs[Boolean](0), row.getAs[Long](1)))
.toList
.sortBy(_._1)
.map(_._2)
val df2 = df.withColumn("portion", when($"is_red", $"value"/lit(sum2)).otherwise($"value"/lit(sum1)))
The extra is_red column can be removed using drop.
Inspired by Shaido, I used an extra column is_red and the spark window function. But I'm not sure which one is better in performance.
df.withColumn("is_red", when(col("type").equalTo("Red"), "Red")
.otherwise("not Red")
.withColumn("portion", col("value")/sum("value)
.over(Window.partitionBy(col"is_Red")))
.drop(is_Red)

y-Shear Matrix as a combination of basic transformation?

I tried to know and searches very much but I didn't find for y-direction shear [1,0,0]
[shy,1,0]
[0,0,1]
You can find the answer at http://web.archive.org/web/20060914224155/http://web.archive.org:80/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q43
In case the link gets broken somehow, here is the relevant part:
A shearing matrix is used to make a 3D model appear to slant sideways.
For example, "italic" text requires each character to slant towards the
right.
In three dimensions six possible shearing directions exist:
o shear X by Y
o shear X by Z
o shear Y by X
o shear Y by Z
o shear Z by X
o shear Z by Y
All six shearing directions may be combined into a single matrix:
| 1 Syx Szx 0 |
| |
| Sxy 1 Szy 0 |
M = | |
| Sxz Syz 1 0 |
| |
| 0 0 0 1 |
| |
Where Sij implements a shear of I by J
Thus, Sxy shears X by Y
In theory, rotation in three dimensions may be considered a combination
of six shearing directions.

Transfer coordinates from one triangle to another triangle

I have two triangles , which can be in any sizes. The problem is that, how I can transfer coordinates from one triangle to another? I know both of triangle position in coordinate system and yes, they both are in one system.
Basically, i have point in triangle1 and I need to transfer it in triangle2.
Reading some posts, I found out that I could be calculated using affine transformation matrix, but I didn't undestand how to solve this with affine transformation matrix.
Thank you for any help.
Let you have unknown affine transformation matrix
| a c e |
M =| b d f |
| 0 0 1 |
The first triangle vertices are (xa1, ya1), (xa2, ya2), (xa3, ya3), and the second triangle vertices have coordinates (xb1, yb1), (xb2, yb2), (xb3, yb3).
Then affine transformation M that transforms the first triangle vertices to the second one vertices is:
M * A = B
where
| xa1 xa2 xa3 |
A =| ya1 ya2 ya3 |
| 1 1 1 |
| xb1 xb2 xb3 |
B =| yb1 yb2 yb3 |
| 1 1 1 |
To find unknown M, we can multiply both sides of the expression by inverse of A matrix
M * A * Inv(A) = B * Inv(A)
M = B * Inv(A)
Inversion of A is rather simple (calculated by Maple, may contain errors due to my typos):
| (ya2-ya3) -(xa2-xa3) (xa2*ya3-xa3*ya2) |
| -(-ya3+ya1) (-xa3+xa1) -(xa1*ya3-ya1*xa3) | * 1/Det
| (-ya2+ya1) -(-xa2+xa1) (xa1*ya2-ya1*xa2) |
where determinant value is
Det = xa2*ya3-xa3*ya2-ya1*xa2+ya1*xa3+xa1*ya2-xa1*ya3
So you can find affine matrix for needed transformation and apply it to coordinates (multiply M and (x,y,1) column matrix)

Using the coordinates of two of a triangle's vertices to calculate the coordinates of the third

I know two coordinates of two vertices in a triangle (not aligned to an axis) and I'm attempting to calculate the coordinates of the third.
a
B ------- C
\ |
\ |
C' \ |
c \ | b
\ |
\ |
\|
A
I know the coordinates of A and B, the lengths of a and c, and that the angle C will always be a right angle. I believe there can only be two possible solutions for the coordinates of C; the one drawn above, and one with C reflected about the line c, approximately at C'. I'd like to calculate both positions.
EDIT:
The source of the triangle is as below.
I know the apex A, the centre of the circle B, the radius of the circle (a) and, from Pythag with (B - A), I know the length of c. I'm trying to find the points at which a line from the apex are at a tangent to each side of the circle, C and C'.
This appears to be an answer to my problem; can anyone elaborate on 'Given two sides of a right triangle, it's easy to find the length and direction of the third side.'.
I know the coordinates of A and B, and the lengths of a and c. From this, I believe there can only be two possible solutions for the coordinates of C
This is not true. There are an infinite number of choices for the position of C, as you don't know the length of b.
For example:
C
|
|
|
|
|
B
\
\
\
c \
\
\
\
A
If you connect C to A, you still maintain those known lengths....
In order for this to be true, you would also need to know one of the angles (such as that it's a right triangle), or the length of b.
It is easy: As the C angle is PI/2 then b=sqrt(c*c-a*a) so you know the lengths of a, b, c.
The coordinates of C and C' = the intersections of two circles:
center B radius a
center A radius b
Solved here for example //A=P1, B=P0, C=P3: https://math.stackexchange.com/questions/187107/calculate-coordinates-of-3rd-point-vertex-of-a-scalene-triangle-if-angles-and
The essential condition for this: if (a<c) otherwise it has no solution.
If you know it's going to be a right triangle, then you know the x and y values will be taken from the other two points.
Point coordsForCompletingTriangleTop(Point a, Point b) {
return new Point(a.x,b,y);
}
Point coordsForCompletingTriangleBottom(Point a, Point b) {
return new Point(b.x,a,y);
}
If cannot be guaranteed that it will be a right triangle, then you do need more information. The length of B, the length of C, or the angle of BCA would be required.
If you assume a and b are the opposite corners of a rectangle
a = (xa, ya)
b = (xb, yb)
then the top right rectangle point is c1 = (max(xa,xb), max(ya,yb))
and the bottom left rectangle point is c2 = (min(xa,xb), min(ya,yb))
Assuming that xa != xb and ya != yb
(xa, ya) A C1 (max(xa, xb), max(ya, yb))
o----------o
|\ |
| \ |
| \ |
| \ |
| \ |
| \ |
| \ |
| \ |
| \ |
o----------o
(min(xa, xb), min(ya, yb)) C2 B (xb, yb)
If your diagonal is going the other way (to test this see if xa > xb) you need to swap min for max on the x
(min(xa, xb), max(ya, yb)) C3 A'
o----------o
| /|
| / |
| / |
| / |
| / |
| / |
| / |
| / |
| / |
o----------o
B' C4 (max(xa, xb), min(ya, yb))
And if you're interested, the full set of solutions actually lies on the circle:
To compute this, suppose we have two points A = (xa, ya) and B = (xb, yb). Then the center point of this circle is c = (0.5 (xa + xb), 0.5 (ya + yb)) - just the midpoint of the A and B. The radius of the circle is r = sqrt( (xb - xa)^2 + (yb - ya)^2) / 2 - using pythagoras' theorem to get the length of the line and halving it. Then any point on the circle can be defined by p = c + (rcos(u), rsin (u)) for some angle u. There are 2 angles which give you the points p = A and p = B so these values of u are not good solutions. You can write out the equation and solve it for these 2 points to give you the values of u which you cannot use.

Resources