Cocos2d / CCDrawNode - How to draw a line? - objective-c

I see there is functionality to draw circles, polys, dot and segments. I dont see one for drawing an A-B line (with given thickness), like ccDrawLine() (which seems to be deprecated).
I need to draw a 'network' between connected nodes. I have the code to draw the network, however ccDrawLine doesn't seem to support aliasing or opacity, like CCDrawNode. It also, without manual intervention, doesn't seem to support batching.
Any suggetions? Would I need to do a load of maths to draw a 2 tri-poly rectangle at the right angle between points?
UPDATE:
Based on comments below... I have an idea on how to do a 'Line' 0,0 to 10,0 with thickness 2, I'd have to do a rect at {0,0.5}, {10,0.5}, {10,-0.5}, {0,-0.5}... I can work out the clockwise triangle points to make a polygon from that easily. I, therefore, could even do horiz/vert ones easily. But how do you do that between {4,5}, {10,7}? Would you do a normal rectangle and apply a transformation matrix to it? Or would you still precalculate each 4 points and then make 2 triangles from it?
UPDATE:
Maybe it'd be better to use a scaled "line" sprite?! Eg: https://stackoverflow.com/a/8760462/224707
UPDATE:
How about a Ribbon? Would that work? Eg: https://stackoverflow.com/a/8178729/224707
Not sure a Ribbon would work for a "network" of points though...
CLARIFICATION:
Imagine this image, but with straight lines and no intersections... Something like this:
(source: relenet.com)
UPDATE:
Apparantly, my post to the Forum did go though last night just before it went down... http://www.cocos2d-iphone.org/forum/topic/224498

A line is a segment. You can take it from here... ;)
Update:
CCDrawNode can draw segments. Segments are lines with defined start and end points.

Related

Making cylindrical space in Repast Simphony?

I am trying to model the interior of an epithelial space and am stuck on movement around the interior edges of a cylindrical space. Basically, I'm trying to implement StickyBorders and keep agents on those borders in a cylindrical space that I am creating.
Is there a way to use cylindrical coordinates in Repast Simphony? I found this example (https://www.researchgate.net/publication/259695792_An_Agent-Based_Model_of_Vascular_Disease_Remodeling_in_Pulmonary_Arterial_Hypertension) where they seem to have done something similar, but the paper doesn't explain methods in much depth, and I don't believe this is an example in the repast simphony models.
Currently, I have a class of epithelial cells that are set up to form a cylinder and other agents start just inside that cylinder. To move, they are choosing their most desired spot (similar to the Zombie code) then pointing to a new location in the direction of that desired location within one grid square of that original location. They check that new point before moving to it and make sure that there are at least two other epithelial cells in the immediate moore neighborhood, to ensure they stay against the wall.
GridPoint intendedpt = new GridPoint((int)Math.rint(alongX),(int)Math.rint(alongY),(int)Math.rint(alongZ));
GridCellNgh<EpithelialCell> nearEpithelium = new GridCellNgh<EpithelialCell>(mac_grid, intendedpt, EpithelialCell.class, 1,1,1);
List<GridCell<EpithelialCell>> EpiCells = nearEpithelium.getNeighborhood(false);
int nearbyEpiCellsCount=0;
for (GridCell<EpithelialCell> cell: EpiCells) {
nearbyEpiCellsCount++;
}
if (nearbyEpiCellsCount<2) {
System.out.println(this + " leaving epithelial wall /r");
RunEnvironment.getInstance().pauseRun();
//TODO: where to go if false
}
I am wondering if there is a way to either set the boundaries of the space to be a cylinder or to check which side of the agent is against the wall and restrict its movement in that direction.
The sticky border code (StickyBorders.java) essentially just checks if the point that the agent moves to is beyond any of the space's dimensions, and if so the point is clamped to that dimension. So, for example, if the space is 3x4 and an agent's movement would take it to 4,2, then that point becomes 3,2 and the agent is placed there. Can you do something like that in this case? If not, can you edit your question to explain why not and maybe that will help us understand better.
The approach we took in that model was to use a 3D grid space with custom borders and query methods. The space itself was still Cartesian - we just visualized it as a cylinder using custom display code. Using the Cartesian grid was an reasonable approximation for this application since the cell dimensions were significantly smaller that the vessel radius, so curvature effects were neglected. The boundary conditions on the vessel space were wrap around in the angular dimension, so that cells could move continuously around the circumference of the vessel, and the axial boundary conditions were also wrapped, as we assumed a long enough vessel length that this would be reasonable. The wall thickness dimension had hard boundaries at the basement membrane (y=0) and at the fluid interface (y=wall thickness).
Depending on which type of space you are using, you will need to implement a PointTranslator or GridPointTranslator that performs the border functions. If you want specific examples of the code I suggest you reach out to the author's directly.

Animating differences between two paths

I don't if what I think can be done or not but I've not found anything online so I need to ask it here.
I have two Path objects in my XAML page but I'm showing just one of them each time.
They represent 2 different emoticons, a smiling face and a sad one.
What I need to do is some kind of interpolation between the paths to animate the transition from the happy face to the sad one and viceversa.
The animation is not a static animation that is played just once but it's rather a gradual animation that follows some data in my view model.
Let's say that I've got a TimeSpan and the face is 100% sad at 00:00:00 while it's 100% happy at 06:00:00.
Given this 2 paths:
path1
<Path Data="M32,39.704002C39.487766,39.704002 46.095413,43.433239 50.098,49.125999 44.997589,45.458061 38.76125,43.27314 32,43.27314 25.23875,43.27314 19.002413,45.458061 13.902,49.125999 17.904589,43.433239 24.512236,39.704002 32,39.704002z M41.9907,22.009001C44.746445,22.009001 46.986,24.246023 46.986,27.00515 46.986,29.763077 44.746445,32 41.9907,32 39.234856,32 36.996002,29.763077 36.996002,27.00515 36.996002,24.246023 39.234856,22.009001 41.9907,22.009001z M22.00955,22.009001C24.765379,22.009001 27.005001,24.246023 27.005001,27.00515 27.005001,29.763077 24.765379,32 22.00955,32 19.253624,32 17.014,29.763077 17.014,27.00515 17.014,24.246023 19.253624,22.009001 22.00955,22.009001z M32,4.9947796C17.110001,4.9947801 4.99547,17.109301 4.99547,32 4.99547,46.890701 17.110001,59.005199 32,59.005199 46.889999,59.005199 59.005199,46.890701 59.005199,32 59.005199,17.109301 46.889999,4.9947801 32,4.9947796z M32,0C49.673199,0 64,14.3268 64,32 64,49.673199 49.673199,64 32,64 14.3268,64 0,49.673199 0,32 0,14.3268 14.3268,0 32,0z" Stretch="Uniform" Fill="#FFFFFFFF" Width="276" Height="276" Margin="0,0,0,0" RenderTransformOrigin="0.5,0.5"/>
path2
<Path Data="M13.613,38.875C18.607058,42.467495 24.713106,44.60701 31.333448,44.60701 37.953793,44.60701 44.05994,42.467495 49.054001,38.875 45.13483,44.449402 38.665386,48.102001 31.333448,48.102001 24.001511,48.102001 17.532166,44.449402 13.613,38.875z M41.115601,21.551001C43.814354,21.551001 46.007,23.740988 46.007,26.44265 46.007,29.143013 43.814354,31.333 41.115601,31.333 38.417046,31.333 36.224998,29.143013 36.224998,26.44265 36.224998,23.740988 38.417046,21.551001 41.115601,21.551001z M21.551451,21.551001C24.249977,21.551001 26.442001,23.740988 26.442001,26.44265 26.442001,29.143013 24.249977,31.333 21.551451,31.333 18.852722,31.333 16.66,29.143013 16.66,26.44265 16.66,23.740988 18.852722,21.551001 21.551451,21.551001z M31.333448,4.8906832C16.753281,4.8906832 4.8913631,16.753981 4.8913627,31.333448 4.8913631,45.913017 16.753281,57.776276 31.333448,57.776276 45.913719,57.776276 57.775574,45.913017 57.775574,31.333448 57.775574,16.753981 45.913719,4.8906832 31.333448,4.8906832z M31.333448,0C48.638233,-3.5527137E-15 62.666996,14.028767 62.666996,31.333448 62.666996,48.638233 48.638233,62.666996 31.333448,62.666996 14.028767,62.666996 -3.5527137E-15,48.638233 0,31.333448 -3.5527137E-15,14.028767 14.028767,-3.5527137E-15 31.333448,0z" Stretch="Uniform" Fill="#FFFFFFFF" Width="276" Height="276" Margin="0,0,0,0" RenderTransformOrigin="0.5,0.5"/>
How can I make this work?
P.S.
Since the question is quite unusual, feel free to insult me but at least try to point me to the right direction :)
There isn't any automatic interpolation between paths, but there are a couple of ways to approach this.
The easiest is to place both paths in the visual tree, set the Opacity of the first to 1.0 and the Opacity of the second to 0.0, then animate the opacities to change and cross-fade between the images.
The next easiest would be to create several intermediate frames and switch between them
For short animations either of these are probably pretty good. For something as long as you're talking it'd be pretty wierd.
To do a full morph you'll need to use code rather than xaml. Identify matching points in each image so you know which points represent the eyes, the nose, the mouth etc. For simple shapes like your faces you may have a one:one match between the points in the start and finish paths and can simply interpolate their coordinates.
If you can draw both the happy and sad faces with the same points in the same order, just with different locations, then it'll be pretty easy: loop through the figures and segments and create a new set with the points interpolated between happy's point and sad's point at the current time.
If the points in the two paths don't represent the same parts of the image then it's more complicated. You'll need to create a mapping between the happy points and the sad points so you know where each point moves in the new version: eyes move to eyes, mouths to mouths, etc.

Blend Pen tool and XAML syntax

I am trying create a basic shape with the Pen tool. All I want is an 'S' like shape that is essentially rotated clockwise 90 degrees. I can't use a TextBlock and just rotate an 'S' though. The reason why is because I need to programmatically set the StrokeThickness dynamically. For the life of me, I can't figure out the darn Pen tool with Blend to accomplish this.
Does anyone know how to use the Pen tool to create an 'S' shape that is rotated clockwise 90? I can only have it 24 dpi high, and at most 56 dpi wide. All I really care about is the XAML with the Path syntax. However, I'm not having much luck.
Any help is appreciated!
The Pen tool definitely takes a bit of practice to get used to. For your scenario though I would just just start out with an Ellipse then place a bit smaller Ellipse inside the center of it. Then select both and do Object -> Combine -> Subtract to make it a hollow ring. Then using a Rectangle repeat the same steps as before to cut it in half. From there make a copy, flip it vertically by Object -> Flip -> Vertical and position the second one to the side to create your sideways "S" shape and again select both and Object -> Combine -> Unite to create just one solid Path giving you an end result of something like this.
<Path Data="M35,0.5 C53.160675,0.5 68.043991,
14.532038 69.399399,32.345566 L69.451454,33.167
L69.52951,33.167 L69.5,34.333992 C69.5,50.626396
82.707596,63.834 99,63.834 C115.2924,63.834 128.5,50.626396
128.5,34.333992 L128.47049,33.167 L133.47049,33.167
L133.5,34.333992 C133.5,53.387825 118.05383,68.834 99,68.834
C80.839325,68.834 65.956001,54.801964 64.600601,36.988438
L64.548546,36.167004 L64.47049,36.167004 L64.5,35.000008
C64.5,18.707603 51.2924,5.5000019 35,5.5000019 C18.707596,5.5000019
5.5,18.707603 5.5,35.000008 L5.5295105,36.167004 L0.52950668,
36.167004 L0.5,35.000008 C0.5,15.946178 15.946175,0.5 35,0.5 z"
Fill="Red" Stroke="Blue" Height="24" Width="56" Stretch="Fill"
UseLayoutRounding="False"/>
However to make life easier for yourself when making complex XAML Path shapes, if you're familiar with tools like Fireworks or Illustrator there are converter tools that allow you export your Vector's into nice XAML which is definitely recommended for the difficult Path creations. Hope this helps.
Here's another option for you, specific to this case: use the Text tool to create the S, rotate it, then convert it to a Path.
At that point, you can do everything you would do otherwise, but saves you the aggravation of trying to draw it. This is also a great way do special text effects.

connect line between two boxes avoiding passing others

I have several boxes (x,y,width,height) randomly scattered around, and some of them need to be linked from point (x1,y1) in box1 to point (x2,y2) in box2 by drawing a line. I am trying to figure a way to make such line avoid passing through any other boxes (other than box1 and box2) by drawing several straight interconnected lines to go around any box in the way (if it is not possible to go with one straight line). The problem is that I don't know an algorithm for such thing (let alone having a technical/common name for it). Would appreciate any help in the form of algorithm or expressed ideas.
Thanks
Assuming that the lines can't be diagonal, here's one simple way. It's based on BFS and will also find the shortest line connecting the points:
Just create a graph, containing one vertex for each point (x, y) and for each point the edges:
((x,y),(x+1,y)) ((x,y),(x-1,y)) ((x,y),(x,y+1)) ((x,y),(x,y-1))
But each of this edges must be present only if it doesn't overlap a box.
Now just do a plain BFS from point (x1,y1) to (x2,y2)
It's really easy to obtain also diagonal lines the same way but you will need 8 edges for each vertex, that are, in addition to the previouses 4:
((x,y),(x-1,y+1)) ((x,y),(x-1,y-1)) ((x,y),(x+1,y-1)) ((x,y),(x+1,y+1))
Still, each edge must be present only if it doesn't overlap a box.
EDIT
If you can't consider space divided into a grid, here's another possibility, it won't give you the very shortest path, though.
Create a graph, in which each box is a vertex and has an edge to any other box that can be reached without the line to overlap a third box. Now find the shortet path using dijkstra between box1 and box2 containing the two points.
Now consider each box to have a small countour that doesn't overlap any other box. This way you can link the entering and the exiting point of each box in the path found through dijistra, passing through the countour.
Put all (x,y) coords of the corners of the boxes in a set V
Add the start- and end coordinates to V.
Create a set of edges E connecting each corner that does not cross any box-side (except for the diagonals in the boxes).
How to check if a line crosses a box side can be done with this algorithm
Now use a path-finding algorithm of your choice, to find a path in the graph (V, E).
If you need a simple algorithm that finds the shortest path, just go with a BFS.
(This will produce a path that goes along the sides of some boxes. If this is undesirable, you could in step 1 put the points at some distance delta from the actual corners.)
If the edges may not be diagonal:
Create a large grid of lines that goes between the boxes.
Throw away the grid-edges that cross a box-side.
Find a path in the grid using a path-finding algorithm of your choice.

Projectile hit coordinates at the apex of its path

I have a projectile that I would like to pass through specific coordinates at the apex of its path. I have been using a superb equation that giogadi outlined here, by plugging in the velocity values it produces into chipmunk's cpBodyApplyImpulse function.
The equation has one drawback that I haven't been able to figure out. It only works when the coordinates that I want to hit have a y value higher than the cannon (where my projectile starts). This means that I can't shoot at a downward angle.
Can anybody help me find a suitable equation that works no matter where the target is in relation to the cannon?
As pointed out above, there isn't any way to make the apex be lower than the height of the cannon (without making gravity work backwards). However, it is possible to make the projectile pass through a point below the cannon; the equations are all here. The equation you need to solve is:
angle = arctan((v^2 [+-]sqrt(v^4 - g*(x^2+2*y*v^2)))/g*x)
where you choose a velocity and plug in the x and y positions of the target - assuming the cannon is at (0,0). The [+-] thing means that you can choose either root. If the argument to the square root function is negative (an imaginary root) you need a larger velocity. So, if you are "in range" you have two possible angles for any particular velocity (other than in the maximum range 45 degree case where the two roots should give the same answer).
I suspect one trajectory will tend to 'look' much more sensible than the other, but that's something to play around with once you have something working. You may want to stick with the apex grazing code for the cases where the target is above the cannon.