I want to highlight a relationship inside a record in graphviz (v 2.38.0) by running a straight edge between two of the elements in that record. However, dot does everything it can to run the edge outside the record node.
The following example shows my problem.
digraph {
rankdir = LR;
splines = line;
i1; i2; i3;
mux [shape=record,label="{ {<i1>i1|<i2>i2|<i3>i3} | MUX | <o1>o1}"];
o;
i1 -> mux:i1;
i2 -> mux:i2;
i3 -> mux:i3;
mux:o1 -> o;
mux:i1:e -> mux:o1:w [color=red];
}
I want the red edge to be a straight line between the ports, inside the record. I don't care if the edge overlays the record label.
Is there a way to force an edge to be a straight line ignoring obstacles, or otherwise instruct dot that an object should ignore if it's overlaying nodes/labels?
This issue is similar to Graphviz edges between ports belonging to the same record node look bad, which doesn't have an answer.
Try: splines = curved;
digraph {
rankdir = LR;
splines = curved;
i1; i2; i3;
mux [shape=record,label="{ {<i1>i1|<i2>i2|<i3>i3} | MUX | <o1>o1}"];
o;
i1 -> mux:i1;
i2 -> mux:i2;
i3 -> mux:i3;
mux:o1 -> o;
mux:i1:e -> mux:o1:w [color=red];
}
Related
Consider a 2D square tiled grid (chess board like) which contains conveyor belt like structures that can curve and move game pieces around.
I need to calculate the turn movement (TURN_LEFT, TURN_RIGHT or STAY), depending on
the direction from which a piece moves onto the field
the direction from which the underlying belt exits the field
Example:
1 2
1 |>X>|>v |
2 | | v |
The belt makes a RIGHT turn. As such, the result of calcTurn(LEFT, DOWN) should be TURN_RIGHT. Meaning the X game piece will be rotated 90° right when it moves over the curve at (1,2).
I already implemented a function but it only works on some of my test cases.
enum class Direction {
NONE,
UP,
RIGHT,
DOWN,
LEFT;
fun isOpposite(other: Direction) = this == UP && other == DOWN
|| this == DOWN && other == UP
|| this == LEFT && other == RIGHT
|| this == RIGHT && other == LEFT
}
data class Vec2(val x: Float, val y: Float)
fun Direction.toVec2() = when (this) {
Direction.NONE -> Vec2(0f, 0f)
Direction.UP -> Vec2(0f, 1f)
Direction.RIGHT -> Vec2(1f, 0f)
Direction.DOWN -> Vec2(0f, -1f)
Direction.LEFT -> Vec2(-1f, 0f)
}
fun getTurnMovement(incomingDirection: Direction, outgoingDirection: Direction): Movement {
if (incomingDirection.isOpposite(outgoingDirection) || incomingDirection == outgoingDirection) {
return Movement.STAY
}
val incVec = incomingDirection.toVec2()
val outVec = outgoingDirection.toVec2()
val angle = atan2(
incVec.x * outVec.x - incVec.y * outVec.y,
incVec.x * outVec.x + incVec.y * outVec.y
)
return when {
angle < 0 -> Movement.TURN_RIGHT
angle > 0 -> Movement.TURN_LEFT
else -> Movement.STAY
}
}
I can't quite figure out what's going wrong here, especially not because some test cases work (like DOWN+LEFT=TURN_LEFT) but others don't (like DOWN+RIGHT=STAY instead of TURN_LEFT)
You're trying to calculate the angle between two two-dimensional vectors, but are doing so incorrectly.
Mathematically, given two vectors (x1,y1) and (x2,y2), the angle between them is the angle of the second to the x-axis minus the angle of the first to the x-axis. In equation form: arctan(y2/x2) - arctan(y1/x1).
Translating that to Kotlin, you should instead use:
val angle = atan2(outVec.y, outVec.x) - atan2(incVec.y, incVec.x)
I'd note that you could achieve also your overall goal by just delineating the cases in a when statement as you only have a small number of possible directions, but perhaps you want a more general solution.
It's not answering your question of why your code isn't working, but here's another general approach you could use for wrapping ordered data like this:
enum class Direction {
UP, RIGHT, DOWN, LEFT;
companion object {
// storing thing means you only need to generate the array once
private val directions = values()
private fun getPositionWrapped(pos: Int) = directions[(pos).mod(directions.size)]
}
// using getters here as a general example
val toLeft get() = getPositionWrapped(ordinal - 1)
val toRight get() = getPositionWrapped(ordinal + 1)
val opposite get() = getPositionWrapped(ordinal + 2)
}
It's taking advantage of the fact enums are ordered, with an ordinal property to pull out the position of a particular constant. It also uses the (x).mod(y) trick where if x is negative, putting it in parentheses makes it wrap around
x| 6 5 4 3 2 1 0 -1 -2 -3 -4 -5
mod 4| 2 1 0 3 2 1 0 3 2 1 0 3
which makes it easy to grab the next or previous (or however far you want to jump) index, acting like a circular array.
Since you have a NONE value in your example (which obviously doesn't fit into this pattern) I'd probably represent that with a null Direction? instead, since it's more of a lack of a value than an actual type of direction. Depends what you're doing of course!
Got this:
for $config.IO.slurp.lines <-> $l {
$l .= trim;
...
}
Get this:
t/01-basic.rakutest ..3/5
Parameter '$l' expects a writable container (variable) as an argument,
but got '# karabiner config file' (Str) as a value without a container.
in sub generate_file at...
I've read the docs on containers but it didn't shed any light on what I can do in this situation aside from maybe assigning $l to a scalar variable, which seems hacky. Is there a way I can containerize $l?
The issue is really that .lines does not produce containers. So with <->, you would bind to the value, rather than a container. There are several ways to solve this, by containerizing as you suggested:
for $config.IO.slurp.lines -> $l is copy {
$l .= trim;
...
}
But that only makes sense if you want to do more changes to $l. If this is really just about trimming the line that you receive, you could do this on the fly:
for $config.IO.slurp.lines>>.trim -> $l {
...
}
Or, if you need to do more pre-processing $l, use a .map:
for $config.IO.slurp.lines.map({
.trim.subst("foo","bar",:g)
}) -> $l {
...
}
Maybe below is what you want? Generally, you read a file via slurp you can comfortably handle its size, or you read a file via lines if you want input taken in lazily, one-line-at-a-time:
my $config = 'alphabet_one_letter_per_line.txt';
my $txt1 = $config.IO.slurp;
$txt1.elems.say; #1
$txt1.print; #returns alphabet same as input
my $txt2 = $config.IO.lines;
$txt2.elems.say; #26
$txt2.join("\n").put; #returns alphabet same as input
Above, you get only 1 element when slurping, but 26 elements when reading lines. As you can see from the above code, there's no need to "...(assign) $l to a scalar variable..." because there's no need to create (temporary variable) $l.
You can store text in #txt arrays, and get the same number of elements as above. And you can just call routines on your stored text, as you have been doing (example below continues $txt2 example above):
$txt2.=map(*.uc);
say $txt2;
Sample Output:
(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
[Note, this question seems to have triggered questions on the use of $txt2.=map(*.uc); versus $txt2.=uc;. My rule-of-thumb is simple: if the data structure I'm working on has more than one element, I map using * 'whatever-star' to address the routine call to each element].
https://docs.raku.org/
I am attempting to build a game that follows the same mechanic as Dragon's Tail featured at the following link http://bit.ly/1CR0iha. I have built a very basic version of level one working using mouse clicks with one open space. I really want it to move on pressmove so that I can drag the pieces to move them rather than on click which will help when there are more than one open space as on level two.
How to confine the movement of the pieces so that they can ONLY move into the open space? My initial though was to place all the pieces into a grid and check for collisions between the various pieces on pressmove and only allow a move if there is no collision.
After some coding I need a sanity check because I am now second guessing my decision. I am asking for on a high level sanity check on my method any insights are most welcome ;);
Once I have set my x and y on mousedown I them do the following on pressmove. I am not limiting my direction which is what I am trying to achieve.
pressMove = function(event){
var pt = this.globalToLocal(event.stageX, event.stageY);
if(pt.x > this.startPosX){
this.dragDirection = 'right';
}
if(pt.x < this.startPosX){
this.dragDirection = 'left';
}
if(pt.y < this.startPosY){
this.dragDirection = 'up';
}
if(pt.y > this.startPosY){
this.dragDirection = 'down';
}
movePiece(event);
}
Moving the piece
movePiece = function(event){
var obj = event.target;
var pt = this.globalToLocal(event.stageX, event.stageY);
switch(this.dragDirection){
case 'up':
obj.y = pt.y;
break;
case 'down':
obj.y = pt.y;
break;
case 'left':
obj.x = pt.x;
break;
case 'right':
obj.x = pt.x;
break;
};
}
you don't need sofisticated collision detection - all you need to know is which are the possible moves (up, down, right, left) allowed for a clicked piece.
you can do this by having a 2d field representing blocked spaces 1 and free spaces 0 like so
A B C D
X 1 0 1 1
Y 1 1 1 1
Z 1 1 1 1
say you click the piece (Y,B) you can see by checking its four neighbouring entries that only the move up is available, similarly for XA and XC. for all other pieces there are no free spaces and thus no possible moves. after moving a piece, make sure its again in a grid position and update the 2d field. i.e. after moving YB up the field should look like this:
A B C D
X 1 1 1 1
Y 1 0 1 1
Z 1 1 1 1
you can make boundary handling easier by surrounding your actual playfield with blocked spaces
Edit: say you only move up/down and left/right. Every move starts at the center of a piece. Around the center there's a deadzone where it's not clear (yet) which direction the move will take. Then your code might look like this:
startDrag(x, y) {
// remember clicked piece p
p <- ...
// remember center positions for p (cX, cY)
(cX, cy) <- ...
// remember offset of cursor to center (oX, oY)
(oX, oY) <- (x - cX, y - cY)
}
continueDrag(x, y) {
// select move direction
if distance between (cX, cY) and (x - oX, y - oY) is within the deadzone
select move direction (up, down, left, right) with least projection error
else
select last move direction
end
// get constrained move direction
switch selected move direction
case up: perform move to (cX, y - oY)
case down: perform move to (cX, y - oY)
case left: perform move to (x - oX, cY)
case right: perform move to (y - oX, cY)
end
}
you can see all of this in action (and a bit more robust) here: http://js.do/code/sliding-puzzle
I have this function:
map(\x -> l ++ [x]) "Show" where l = ""
I want the values of l to be saved at every step of the map function (e.g. I don't want to return ["S","h","o","w"], I want it to return ["S","Sh","Sho","Show"])
Can someone help me?
You're nearly there:
inits (x:xs) = map (\ys -> x:ys) ([]:inits xs)
inits [] = []
but note that you can rewrite (\ys -> x:ys) as (x:), which puts x at the front of each list it encounters, giving
inits (x:xs) = map (x:) ([]:inits xs)
inits [] = []
This works because map (x:) ([]:inits xs) gives you (x:[]) : map (x:) (inits xs), so everything in the list starts with x, and the first one is just [x]. That's true also of inits xs, so each gets one element longer.
There's a standard function
As usual, you're not the first to want this, which is why the function is defined already in Data.List. All you need to do is add
import Data.List
to the top of the program and you get inits predefined.
How is inits defined there?
Now if you look up hoogle for that, http://www.haskell.org/hoogle/?q=inits you can click through to find
inits :: [a] -> [[a]]
inits xs = [] : case xs of
[] -> []
x : xs' -> map (x :) (inits xs')
which is almost exactly the same idea, but in a case statement, which moves the pattern matching to be internal to the function.
Notice that this is slightly different to what you wanted, because you get a [] at the front of your answer, but you could use tail to get rid of that.
myinits = tail.inits
How can you find if there's already a function?
You wanted to turn a list into a list of lists. That should have type [a]->[[a]]. You can search for that on hoogle http://www.haskell.org/hoogle/?hoogle=[a]+-%3E+[[a]] and it's the top answer (more generally it might be lower down and you'd have to browse a bit.
This works for a lot of standard functions, since hoogle indexes all of base for a start.
Use scanl :
Prelude> scanl (\a c -> a++[c]) "" "Show"
["","S","Sh","Sho","Show"]
An efficient version:
Prelude> map reverse . scanl (flip (:)) [] $ "Show"
["","S","Sh","Sho","Show"]
Use Data.List.inits:
> tail $ inits "Show"
["S","Sh","Sho","Show"]
Just combine inits and tail functions from Prelude:
tail . inits $ "Show"
I am working on a dot file to present the layering for nodes.
The figure I have is this one.
(sorry, I do not have enough reputation to post images..)
http://www.flickr.com/photos/40328682#N03/8473003861/in/photostream/lightbox/
However, I want the trees (blue nodes) not to be compressed and occupy only one layer for each tree. I draw an example by adding invisible nodes and more edges, like this:
http://www.flickr.com/photos/40328682#N03/8474093000/in/photostream/lightbox/
I tried $ rank = same $ to make the yellow node and blue node (top one) on the same level, but I cannot add more layers without inserting invisible nodes.
Is there any way I can add more layers between different ranks without adding invisible nodes? Thanks a lot!
If there are no connections between sub-graphs, then there is no way to control their positioning. Using rank=same is a common approach in the legend on the left along with the invisible nodes to force structure into the layout.
If you simply need to add a minimum amount of space between two nodes, then you can use the minlen = attribute on a hidden edge to force the required separation. This is also explained in subgraph cluster ranking in dot.
This is demonstrated in:
digraph {
node [label = ""];
A; B; C; D;
E [style = invis];
{ node [shape = box, label = ""];
1 -> 2;
3 -> { 4; 5; 6; 7; 8; 9; 10; 11; 12; }; 5 -> 13; 7 -> 14; 10 -> 15; 12 -> { 16; 17; }; 16 -> 18;
19 -> { 34; 35; 36; 37; 38; 39; 40; 41; }; 35 -> 42; 36 -> 43; 40 -> { 45; 46; }; 41 -> 44;
20 -> { 21; 22; 23};
}
{ edge [weight = 10];
A -> B [minlen = 2];
B -> C [minlen = 3];
C -> D [minlen = 3];
D -> E [style = invis];
}
{ rank = same; A -> 1; }
{ rank = same; B -> 3; }
{ rank = same; C -> 19; }
{ rank = same; D -> 20; }
}
The last tree (referenced from D would fall under the ellipses on the left without the hidden E. If this is not acceptable, then a hidden edge from one of the nodes in the tree above needs to be connected to node 20.
The spacing between the ellipses can be adjusted with the minlen = attributes.