I have some code that is working pretty well to find the angle between two points temp and newpoint:
CGPoint newpoint=CGPointMake(newX,newY );
CGPoint diff = ccpSub(temp.position, newpoint);
float rads = atan2f( diff.y, diff.x);
float degs = CC_RADIANS_TO_DEGREES(rads);
CCLOG(#"now: %f,%f to:%f,%f degs:%f",temp.position.x,temp.position.y,newX,newY,degs);
It correctly works most of the time, but for some points it has errors. Here is part of the log:
2011-12-13 11:05:19.401 Bells[2303:c503] now: 368.603271,147.813110 to:265.566284,210.476471 degs:-30.655481
2011-12-13 11:05:20.417 Bells[2303:c503] now: 77.030159,167.413544 to:184.491669,117.072098 degs:154.254135
2011-12-13 11:05:20.417 Bells[2303:c503] now: 355.119720,121.963585 to:307.802826,49.591988 degs:56.634174
2011-12-13 11:05:20.418 Bells[2303:c503] now: 465.000000,89.771843 to:373.258270,15.000000 degs:39.249508
2011-12-13 11:05:20.419 Bells[2303:c503] now: 307.277588,69.095749 to:363.791168,174.386093 degs:-118.026299
2011-12-13 11:05:21.417 Bells[2303:c503] now: 190.993607,194.947479 to:101.720551,255.007492 degs:-33.194214
2011-12-13 11:05:21.418 Bells[2303:c503] now: 23.930172,27.319054 to:85.588303,15.000000 degs:167.615768
2011-12-13 11:05:21.418 Bells[2303:c503] now: 365.033630,218.904007 to:277.799194,141.605042 degs:41.585751
2011-12-13 11:05:21.419 Bells[2303:c503] now: 221.239227,153.457306 to:116.308037,87.374733 degs:32.344673
2011-12-13 11:05:22.433 Bells[2303:c503] now: 140.302948,260.575500 to:191.313812,208.167419 degs:133.118576
2011-12-13 11:05:22.433 Bells[2303:c503] now: 16.781921,224.473648 to:90.456161,153.657745 degs:135.340363
2011-12-13 11:05:22.434 Bells[2303:c503] now: 307.802826,49.591988 to:391.818512,15.000000 degs:156.793350
2011-12-13 11:05:22.435 Bells[2303:c503] now: 265.566284,210.476471 to:311.953583,114.193481 degs:115.011368
2011-12-13 11:05:22.435 Bells[2303:c503] now: 140.599457,296.268768 to:39.459061,305.000000 degs:-4.328590
2011-12-13 11:05:22.436 Bells[2303:c503] now: 459.438629,190.859222 to:465.000000,96.320923 degs:92.733452
This line in particular is an example of the problem:
2011-12-13 11:05:21.418 Bells[2303:c503] now: 23.930172,27.319054 to:85.588303,15.000000 degs:167.615768
This distance between these two points is very approximately horizontal, thus you'd expect an angle that is quasi horizontal. Yet, the angle is nearly vertical. I'm not a whiz at trig but clearly there is a math issue that is affecting only some points here. Any ideas?
you can use ccpAngle(<#CGPoint a#>, <#CGPoint b#>) or ccpAngleSigned(<#CGPoint a#>, <#CGPoint b#>), and yes there is an angle between 2 points, a point is a vector.
remember that cocos use degrees and math done with CGPoints uses Radians. also remember that cocos uses rotations clockwise and CGPoints angles are anticlockwise.
You can use as suggested helpers as CC_RADIANS_TO_DEGREES
Related
I am a newbie of xaringan and trying to draw some pictures using tikz package.
I was wondering how to run tikz in xaringan slides.
My codes are:
---
title: "Econ"
subtitle: "Lecture 1"
author: "Instructor"
institute: "College"
date: "`r Sys.Date()`"
output:
xaringan::moon_reader:
css: [default, metropolis, metropolis-fonts, "styles.css"]
lib_dir: libs
nature:
highlightStyle: arta
highlightLines: true
countIncrementalSlides: false
---
```{r,engine='tikz'}
\tikzset{every picture/.style={line width=0.75pt}} %set default line width to 0.75pt
\begin{tikzpicture}[x=0.75pt,y=0.75pt,yscale=-1,xscale=1]
%uncomment if require: \path (0,379); %set diagram left start at 0, and has height of 379
%Rounded Rect [id:dp1857476422681199]
\draw [fill={rgb, 255:red, 241; green, 192; blue, 192 } ,fill opacity=1 ] (228,123) .. controls (228,114.16) and (235.16,107) .. (244,107) -- (343,107) .. controls (351.84,107) and (359,114.16) .. (359,123) -- (359,171) .. controls (359,179.84) and (351.84,187) .. (343,187) -- (244,187) .. controls (235.16,187) and (228,179.84) .. (228,171) -- cycle ;
%Shape: Rectangle [id:dp08440493370073976]
\draw [fill={rgb, 255:red, 226; green, 233; blue, 201 } ,fill opacity=1 ] (415,115) -- (525,115) -- (525,179) -- (415,179) -- cycle ;
%Rounded Single Corner Rect [id:dp01343887372328001]
\draw [fill={rgb, 255:red, 0; green, 0; blue, 0 } ,fill opacity=0.05 ] (64,129.52) .. controls (64,122.27) and (69.87,116.4) .. (77.12,116.4) -- (170,116.4) -- (170,182) -- (64,182) -- cycle ;
%Straight Lines [id:da9440635149995973]
\draw (171,144) -- (218,144) ;
\draw [shift={(221,144)}, rotate = 180] [fill={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.08] [draw opacity=0] (10.72,-5.15) -- (0,0) -- (10.72,5.15) -- (7.12,0) -- cycle ;
%Straight Lines [id:da7316344569835018]
\draw (361,145) -- (405,145) ;
\draw [shift={(408,145)}, rotate = 180] [fill={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.08] [draw opacity=0] (10.72,-5.15) -- (0,0) -- (10.72,5.15) -- (7.12,0) -- cycle ;
%Curve Lines [id:da512763546270846]
\draw (415,179) .. controls (380.35,241.37) and (217.31,242.97) .. (171.36,183.81) ;
\draw [shift={(170,182)}, rotate = 54.2] [fill={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.08] [draw opacity=0] (10.72,-5.15) -- (0,0) -- (10.72,5.15) -- (7.12,0) -- cycle ;
\draw (280.56,238.98) -- (311.32,217.88)(282.27,217.6) -- (309.61,239.25) ;
% Text Node
\draw (420,125) node [anchor=north west][inner sep=0.75pt] [align=left] {{\fontfamily{ptm}\selectfont \textit{\textbf{y} }}\\{\fontfamily{ptm}\selectfont \textit{variables}}};
% Text Node
\draw (75,129) node [anchor=north west][inner sep=0.75pt] [align=left] {{\fontfamily{ptm}\selectfont \textit{\textbf{x}}}\\{\fontfamily{ptm}\selectfont \textit{variables}}};
% Text Node
\draw (271,138.4) node [anchor=north west][inner sep=0.75pt] {$function$};
\end{tikzpicture}
```
My code generates the following error with the same weird outcome, which is just the copy of my codes.
Error in if (to_svg) tinytex::latexmk(texf, "latex") else tinytex::latexmk(texf) : argument is of length zero
You are having the error Error in if (to_svg) tinytex::latexmk(texf, "latex") else tinytex::latexmk(texf) : argument is of length zero, due to most probably, you don't have the {tinytex} package installed. Because tikz engine requires the {tinytex} package to compile TikZ graphics to other foramts (e.g., svg or png).
So try installing the {tinytex} package at first. See here how to do that.
Then also add the echo=FALSE in chunk option.
Given the following custom types:
type player = Orange | Red | Blue | White ;;
type piece = Knight of player | Town of player | City
of player | Road of player | Wool of player |
Brick of player | Lumber of player | Grain of
player | Ore of player ;;
All four players pieces are stored in a single piece array. Write functions
getplayer : piece -> player = <fun> that given a piece, it returns the
player that owns it.
# getplayer ( Town Orange ) ;;
- : player = Orange
# getplayer ( Wool Red ) ;;
- : player = Red
I'm trying to do it in a long way since It's the only one thats working for me. I did try pattern matching and putting for example | (_ Blue) -> Blue but I'm getting either two of the errors, value is piece but unit is expected or It's giving a syntax error at getplayer (Knight Blue);; at the first bracket when I call the function. I was just wondering if there are any faster ways to do this? Also, when I put first if instruction to return empty bracket if it receives empty brackets, I get an error that the type is wrong.
type player = Orange | Red | Blue | White ;;
type piece = Knight of player | Town of player | City
of player | Road of player | Wool of player |
Brick of player | Lumber of player | Grain of
player | Ore of player ;;
let rec getplayer = fun value ->
if value = (Knight Orange) then Orange
else if value = (Knight Red) then Red
else if value = (Knight Blue) then Blue
else if value = (Knight White) then White
else if value = (Town Orange) then Orange
else if value = (Town Red) then Red
else if value = (Town Blue) then Blue
else White;;
getplayer (Knight Blue) ;;
Pattern matching:
let rec getplayer = fun value -> match value with
| (_ Orange) -> Orange
| (_ Red) -> Red
| (_ Blue) -> Blue
| (_ White) -> White;;
getplayer (Knight Blue) ;;
When I try to pattern like this, my any value _ is obviously wrong notated or not placed at the right position since I always get the error
Syntax error: ')' expected
This '(' might be unmatched
I wanted to have (anything Color) and then return just that color since the player doesnt realy matter.
I also don't understand how to write the empty piece in a way that If you get () it returns () as well.
You seem to be asking whether there's a faster way to calculate your function. The answer is yes, it's faster to do a pattern match than a series of if tests. OCaml excels at compiling its pattern matches into efficient code.
If you give us an example where you can't get pattern matching to work, we can suggest how to fix it. I don't really want to write your code for you, as this is obviously an assignment.
For your second question, the type of () is unit. The type of (Knight Orange) (say) is piece. They aren't the same type at all. So that's what the compiler is telling you.
Update
You're trying to use a pattern of the form (_ Orange). But OCaml patterns don't work like that (as you know). You can't have a wild card for just the value constructor (like Knight), since in general the values inside the constructors can be of different types.
Instead of enumerating all the players, you can enumerate all the pieces:
let getplayer piece =
match piece with
| Knight p
| Town p
| City p
| Road p
| Wool p
| Brick p
| Lumber p
| Grain p
| Ore p -> p
Since every piece has a player, it might be better to structure them like this:
type player = Orange | Red | Blue | White
type piece_t =
| Knight | Town | City | Road | Wool
| Brick | Lumber | Grain | Ore
type piece = piece_t * player
I.e., you can have a piece represented by a pair.
Then you can write your function like this:
let getplayer (piecet, player) = player
I'd like to get string from user, parse it, then run the parsed commands.
The string input will be something like "F20N20E10L10", guaranteed no spaces.
This input I want to convert to LOGO commands with substitutions like these:
"F" → fd
"N" → seth 0 fd
"E" → seth 90 fd
"L" → lt 90 fd
So the string input above would be converted to these LOGO commands:
fd 20 seth 0 fd 20 seth 90 fd 10 lt 90 fd 10
All Forth dialects allow input, and interpreting a string of commands.
But I can't find any with search and replace string operations. Is this possible in any dialect of LOGO? Willing to consider any.
Thank you for reading.
It's been a while since I've written any Logo, so I'm not sure if this is the easiest way, but here's one way you can do it. The general idea is you can work with strings as lists of characters, using FIRST, LAST, BUTFIRST, and BUTLAST to get at different parts of the string. (I tested this on the first two online Logo interpreters I could find -- http://www.logointerpreter.com/turtle-editor.php and http://www.calormen.com/jslogo/ -- and it ran fine on both, but you might need some small changes for other Logo dialects.)
TO RUN_COMMANDS :commands
IF (EMPTY? :commands) [STOP]
MAKE "first_command (FIRST :commands)
MAKE "rest_of_commands (BUTFIRST :commands)
IF (NOT EMPTY? :rest_of_commands) [MAKE "split (GET_NUMBER :rest_of_commands ")]
MAKE "numeric_argument (LAST :split)
MAKE "rest_of_commands (FIRST :split)
RUN_SINGLE_COMMAND :first_command :numeric_argument
RUN_COMMANDS :rest_of_commands
END
TO MERGE_STRING :word :characters
IF (NOT EMPTY? :characters) [OP (MERGE_STRING (WORD :word (FIRST :characters)) (BUTFIRST :characters))]
OP :WORD
END
TO GET_NUMBER :word :number
IF (AND (NOT (EMPTY? :word)) (IS_DIGIT (FIRST :word))) [OP (SE (GET_NUMBER (BUTFIRST :word) (LPUT (FIRST :word) :number))]
OP (SE (MERGE_STRING " :word) (MERGE_STRING " :number))
END
TO IS_DIGIT :character
OP (OR
:character = "0
:character = "1
:character = "2
:character = "3
:character = "4
:character = "5
:character = "6
:character = "7
:character = "8
:character = "9)
END
TO RUN_SINGLE_COMMAND :command :parameter
(PRINT_COMMAND :command :parameter)
IF (:command = "F) [FD :parameter]
IF (:command = "B) [BK :parameter]
IF (:command = "L) [LT 90 FD :parameter]
IF (:command = "R) [RT 90 FD :parameter]
IF (:command = "N) [SETH 0 FD :parameter]
IF (:command = "S) [SETH 180 FD :parameter]
IF (:command = "E) [SETH 90 FD :parameter]
IF (:command = "W) [SETH 270 FD :parameter]
END
TO PRINT_COMMAND :command :parameter
IF (:command = "F) [PRINT (SE "FD :parameter)]
IF (:command = "B) [PRINT (SE "BK :parameter)]
IF (:command = "L) [PRINT (SE "LT 90 "FD :parameter)]
IF (:command = "R) [PRINT (SE "RT 90 "FD :parameter)]
IF (:command = "N) [PRINT (SE "SETH 0 "FD :parameter)]
IF (:command = "S) [PRINT (SE "SETH 180 "FD :parameter)]
IF (:command = "E) [PRINT (SE "SETH 90 "FD :parameter)]
IF (:command = "W) [PRINT (SE "SETH 270 "FD :parameter)]
END
Then, try running:
RUN_COMMANDS "F20N20E10L10
This prints and executes the following:
FD 20
SETH 0 FD 20
SETH 90 FD 10
LT 90 FD 10
Some Explanation
RUN_COMMANDS is the main function. It:
Extracts the first letter from the sting (I'm assuming each command is abbreviated as a single letter)
Calls GET_NUMBER which extracts a number (which could be multiple characters) from the start of the string.
Passes the single-letter abbreviated command and number to RUN_SINGLE_COMMAND
Recurses to repeat the process
IS_DIGIT is used within GET_NUMBER to check if a character is numeric (although I would bet some Logo dialects have a built-in function for this.)
MERGE_STRING is used because I had some multi-character Words ("word" is Logo-speak for a string) which I had turned into Lists of single-character Words, and I wanted to merge the list back into a single Word. This might not actually be necessary, though.
RUN_SINGLE_COMMAND executes each individual command that was parsed from the input string. I just used a big IF statement, rather than using a function which interprets the string as code as you suggested. (Some Logo dialects might have such a function, but I'm not sure of a standard one.) RUN_SINGLE_COMMAND also calls PRINT_COMMAND, which prints out the unabbreviated command as it's run.
Potential Stack Overflows
I used lots of recursion because it's more idiomatic of Logo, and because Logo dialects often don't have a lot of looping constructs (other than REPEAT). But I did it in a careless way, since I was just writing this quickly to give you the general idea. In particular, I didn't worry about stack overflows (no pun intended), which I think could occur if you provided a long input string. To deal with this, you should make sure any recursive path that can be called arbitrarily many times is a tail call, which Logo will optimize away.
At a glance, it looks like RUN_COMMANDS is fine but MERGE_STRING and GET_NUMBER are reversed -- instead of IF <condition> [<recursive_call>] followed by OUTPUT <return_value>, it would be better to do IF (NOT <condition>) [OUTPUT <return_value>] followed by <recursive_call>. Testing for stack overflows and applying this fix I have left as an exercise for the reader. :)
I am trying to draw a line that goes through the given blobs. The following is a given example
I want a curve line that goes through multiple blobs in horizontal direction as shown below.
Just as example:
import cv2
import numpy as np
img = cv2.imread('image.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
(_, contours, _) = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
# biggest area
target = max(contours, key=lambda x: cv2.contourArea(x))
cv2.drawContours(img, [target], -1, [0, 0, 255], -1) # debug
# just example of fitting
x = target[:, :, 0].flatten()
y = target[:, :, 1].flatten()
poly = np.poly1d(np.polyfit(x, y, 5))
for _x in range(min(x), max(x), 5): # too lazy for line/curve :)
cv2.circle(img, (_x, int(poly(_x))), 3, [0, 255, 0])
cv2.imshow('result', img)
cv2.waitKey(0)
Just for fun, and employing the Perl philosophy of TMTOWTDI ("There's More Than One Way to Do It)", I extracted all the white points of your contours into a file called points.dat and fed that into gnuplot to fit a curve, which gave me a formula for a best fit line of:
y=3.10869110524588e-07*x*x*x -0.000972406154863963*x*x + 0.861790477479291*x + 307.220397010312
And then I plotted that in red on your original contours using awk and ImageMagick.
#!/bin/bash
convert contours.jpg -colorspace gray -threshold 50% txt: | awk -F: '/white/{print $1}' | tr ',' ' ' > points.dat
{ echo 'f(x) = a*x**3 + b*x**2 + c*x + d'; \
echo 'fit f(x) "points.dat" via a, b, c, d'; \
echo 'print a,"*u^3 + ",b,"*u^2 + ",c,"*u + ",d'; \
} | gnuplot 2>&1 | tail -1
awk 'BEGIN{
for(x=0;x<1504;x++){
y=3.10869110524588e-07*x*x*x -0.000972406154863963*x*x + 0.861790477479291*x + 307.220397010312
y=int(y)
print "point ",x,y
}
}' /dev/null > p.mvg
convert contours.jpg -draw #p.mvg z.png
The start of points.dat looks like this:
769 453
770 453
771 453
772 453
773 453
769 454
765 455
766 455
767 455
768 455
...
...
The start of p.mvg looks like this:
fill red
point 0 307
point 1 308
point 2 308
point 3 309
point 4 310
point 5 311
point 6 312
point 7 313
point 8 314
...
...
I'm trying to create a mapping for tile/pixel positions in one tiled image dataset to tile/pixel position in a different dataset (that roughly cover the same image area). Due to rotations of the imaged area, panning axis, translations, and scale changes, there are many unknowns to account for in this mapping. This situation is illustrated below, where the rectangles represent the imaged area for each tile, and the layout of the tiles is governed by the relationship between the panning axis (black lines) and the camera axis:
The problem reduces down to the following linear system which takes into account the scanning axis being rotated with respect to the camera axis differently in the two datasets, plus rotation,scale,and translations between the imaged areas in the two datasets. Unfortunately I'm not sure how to go about solving for the unknowns:
|tx ty|X|a b|+|px py|X|e f|+|i j|=|tx* ty*|X|k l|+|px* py*|
|c d| |g h| |m n|
The unknowns in this system are (a,b,c,d,e,f,g,h,i,j,k,l,m,n) and basically describe a mapping from tile and pixel positions in dataset1 (tx,ty,px,py) to tile and pixel positions in dataset2(tx*,ty*,px*,py*). Coming up with 14 (or more) such correspondences isn't too big a deal for me, as I have a log-polar image registration that works pretty well for affine mapping a tile from dataset1 to a tile in dataset2 if they contain sufficient image overlap. The problem is I'd rather get the above mapping determined rather than doing this registration between every single tile in dataset1 and 2 would take forever!!.
Any help greatly appreciated!
-Craig
Edit:
I just figured out I can rearrange the problem like so (I think?):
|tx ty px py 1|X|a b|=|tx* ty* px* py* 1|X|k l|
|c d| |m n|
|e f| |1 0|
|g h| |0 1|
|i j| |1 1|
This is looking closer to what I need, but I still need help trying to figure out how to convert the answer I'd get back into a form I could use (most importantly I think I'd need to explicitly know (k,l,m,n) to convert the mapped coordinate back into a tile and pixel position in the target.... no?
Edit2: Changed the notation to be correct for matrix multiplication
Edit3: Added illustration images since I now can!
OK, I've long since figured out the problem, but am posting here for documentation.
|tx ty px py 1|X|a b|=|tx* ty* px* py* 1|X|k l|
|c d| |m n|
|e f| |1 0|
|g h| |0 1|
|i j| |1 1|
can be rewritten conveniently as:
|tx ty px py| X A X B + T = |tx* ty* px* py*| X C
where the matrices A and C describe the transform from the slide coordinate system to a global |x y| coordinate system, and 'B + T' is an affine transform |x y| -> |x* y*|
rewritten again:
|tx ty px py 1 tx* ty*| X |A*| = |px* py*|
|B |
|T |
|C*|
shows that
|B| == |e f|
|T| |g h|
|i j|
A* X inv(B) = |a b|
|c d|
-C* = |k l|
|m n|
To determine the linear least-squares solution to the problem from correspondences:
points on slide 1
tp1 = [[tilex,tiley,pixelx,pixely],
...,]
to corresponding points on slide 2
tp2 = similar as above
def findABC(tp1,tp2):
dp1 = np.hstack([tp1,np.ones([len(tp1),1]),tp2[:,0:2]])
dp2 = tp2[:,2:4]
E,_,rank,_ = np.linalg.lstsq(dp1,dp2)
if rank == 7:
B = E[2:5]
A = np.dot(E[0:2,0:2],np.linalg.inv(E[2:4,0:2]))
C = -E[5:7]
return A,B,C
def SlideToGlobal(X,tp):
return np.dot(tp,X)
def GlobalToSlide(X,p):
tptp = np.dot(p,n.linalg.inv(X[0:2,0:2]))
tpoints = np.floor(tptp)
ppoints = tptp-np.dot(tpoints,X[0:2,0:2])
tp = np.hstack([tpoints,ppoints])
return tp