I am using fabric.js for creating a canvas project. I have created a line using the framework. However, is there a way to set a fixed length on the line. Reason being, the line is draggable and it stretches.
line = makeLine([ 250, 125, 250, 175 ]),
It got quite complicated in the comments so let's sum up few things:
Here's a solution for the simple case:
In your http://jsfiddle.net/sprakashg/rbhhP/ you have few lines like this:
var p = e.target;
p.line1 && p.line1.set({ 'x2': p.left, 'y2': p.top });
Here, the line1 is your Line and p is your Circle.
You can compute the initial length of the line and store it. Next, you can compute a current line direction, which is from line.p1 to position of p. Now, if you normalize this direction and multiply by the initial line length you'll get the new direction, pointing at your circle, but keeping initial line length. Add it to your line start and you can store this value in p.line1.set().
This will work if you have two circles connected with a line, but if you have few lines connected to the single circle, then you'll not be able to move it.
Solution for more complex case:
In your Stickman case you can't move a knee because there's only one another point that satisfies your lines length constraints. In such case I'd add a simple hierarchy to the model.
If you assume some Circle to be the root of the model, then all other objects are leaves and branches of some model tree. Now, when you move some circle, you should do the computations mentioned above just for the line, that connects it with the parent.
Then you can take all the circles below in your model hierarchy and move them by the same amount that you moved your main Circle.
With this approach, when you try to move a knee then your pelvis-knee line will move with your mouse but keep its length (as you want to). But during the movement of the knee the rest of a leg will move by the same amount, so in effect you'll also keep the length of a knee-ankle line.
Related
Given a collection of points, I'd like to find the center of a bounding box (fixed-length and width) that maximizes the number of points within said box. I'm at a loss for an efficient way to do this.
Algorithm with complexity O(N^2*logN) (I hope that better one exists):
Edit: article exploiting interval trees claims O(NlogN) complexity
Sort data array A by X coordinate.
Scan A with sweep line left to right.
For every point in A get LeftX = A[k].X - left coordinate of vertical band, find the rightmost coordinate of vertical band RightX = LeftX + Width.
Copy points inside the band to another array B.
Sort B by Y-coordinate.
Scan B width sweep line top to down.
For every point B[i] get TopY = B[i].Y - top coordinate of rectangle, calculate BottomY = TopY + Height.
Use binary search in B:
B[j] is the last bottom point in B with B[j].Y <= BottomY.
Find number of points in the current rectangle:
Number of points is N(k, i) = j - i + 1
Check whether N(k, i) is maximum among others
This seems like a difficult problem, here is my idea:
Hold a graph, each node holds a rectangle and a subset of points. the rectangle defines the area where placing the bounding box in would overlap all the points in the subset.
To build the graph:
Start with a root node holding the empty set and the rect [top:-inf, bottom:inf, left:-inf, right:inf]
For each point in the tree call this recursive function with the root node (pseudo code):
function addPoint(node, point)
// check that you didn't already try to add this point to this node
// node.tested can be a hash set
if(node.tested contains point)
return
node.tested.add(point)
newRect = node.rect.intersectWith(boundingBoxAround(point))
// if the bounding box around the point does not intersect the rectangle, return
if(newRect is invalid) // rect is invalid if right<left or bottom<top
return
node.addChild(new node(newRect, node.pointSet U {point})
for each child of node
addPoint(child, point)
Now you just pick the node with the largest subset, you can keep track of that when building the graph so you don't need to run through the graph again.
I hope my idea is clear, let me know if I can explain it better.
I am currently trying to write a shader in unity that draws a triangular pattern around countries in a risk-styled game if both countries are not owned by the same player (visual aid to see your borders).
Right now, I'm having an issue with making the shader set the countries properly.
It always sets country 0 to the left, and country 1 to the right - country 0 and 1 are set programically.
The line, a border, can be between 0 and 359 degrees.
How I find the countries 0 and 1 is I draw 3 points to the left and right of the midpoint of the line, one .01f, one .1f and one 1f away from the midpoints in each direction, then spin them around the midpoint to the appropriate location.
After that I do an even-odd check to see if the points are inside or outside of each country, and compare the weight results (closest gets 3 points, mid gets 2, furthest gets 1, just in case someone builds a really screwed up country that flanks the other country).
In my test map, a close to equally sliced octagon, the borders showed up correctly (after I reversed the positions of country 0 and 1 in the event the angle was over 90 and less then or equal 180). Worked without a flaw, but in other maps it doesn't work very well.
Everything but the country allocation works well, so I'm curious if anyone knows of a better way to figure out which point is to the left or a spun line, or a better conceptual way to handle this.
That above is basically when I'm doing, red being left right being blue, then I'm just checking 3 different spots then weighing in the lefts and rights found with even/odding it into the appropriate countries (one at +/- .01, the other at +/- .1 and the third 1, in case of even/odd rounding issues with closeness).
I then flip them if I find that country A is to the right, as it is on the left according to the angles I had draw. (my shader renders left first and right second, hence why I do this).
which way is left/right on a line?
From last edit is this not your case. Why not use dot product?
So if the line goes in -x direction the result is negative and if in the +x direction then the result is positive. if the result is zero that means the line goes up or down only or it is juts a point. If you need specific direction instead of left/right then use appropriate a vector instead of x axis.
dot(a,b)=a.x*b.x+a.y*b.y in 2D
dot(a,b)=a.x*b.x+a.y*b.y+a.z*b.z in 3D
Image is relevant for cases where a vector is in unit size in that case the result of dot is perpendicular projection of b into a just like on image
on which side is some point?
I think this is what you need.
As you can see if you handle line (P0,P1) and point P you want to classify as triangle then its polygon winding determines also the side of the line. So for implicit axis directions:
CW(clockwise) polygon winding means right side of the line
CCW(counter-clockwise) polygon winding means left side of the line
How to get winding? ... simply compute normal vector and get its Z coordinate. Its polarity (sign) determines winding (CW/CCW or the other way around depends on the coordinate system).
normal vector is computed as cross product of the two vertices of triangle (P1-P0)x(P-P1)
No need to compute other axises just the z so:
normal.z = ((P1.x-P0.x)*(P.y-P1.y)) - ((P1.y-P0.y)*(P.x-P1.x))
Now just do if (normal.z<0) ... else ... it should never be zero unless you call it for point on the line or the line is a point ... look here at similar question: Determine rotation direction /toward/ variable point on a circle
If I have line like this (a xy plot in the future)
`Canvas {
id:canvas
onPaint:{
var ctx = canvas.getContext('2d');
ctx.moveTo(0,0);
ctx.lineTo(50,20);
ctx.lineTo(50,70);
// etc...
}
}`
so, is there a good way to check mouse press event on this line? i.e. If I have a plot and want to show context menu on right click on graph line
Unfortunately, AFAIK, you should keep track of what you draw. Canvas doesn't store drawn stuff as vector graphics(again, AFAIK), but on a raster, so there's no way to get it to tell you where the lines/points are.
You could push each point you pass to ctx.moveTo and ctx.lineTo to a list or other structure. Then, on click, iterate over all line segments (designated by pairs of points you stored) and check if distance of the clicked point to the line segment is within some selection tolerance distance you want.
To check the distance, you can use this:
Shortest distance between a point and a line segment
I don't know if this is the simplest way, but it works.
I am trying to write an application to draw schematic diagrams which contain rectangles, lines and circles. Now I want to add another functionality to drag a rectangle to different position. The problem I am facing is to detect whether I have clicked within a rectangle or not. I know there is a function like Rectangle.Contains(Point). To use such method I need to use a for loop to check against each rectangle. If I have a large number of rectangles present, then its not wise to use this method. Is there any other way to do this task.
You need a computer graphics textbook, this and similar problems are often discussed.
If memory serves me, make sure the point is below the top edge of the rectangle, above the bottom edge, left of the right edge and right of the left edge.
Regarding testing a bunch of rectangles in a loop. Consider having a circle that each rectangle fits in, a bounding circle. First test to see if the point is farther from the origin of the circle than the radius of the circle. If so there is no need to test the rectangle, its a miss. OK, that was a very theoretical answer. In reality calculating the distance from the point to the origin can be a very expensive calculation, it involves a square root, it may be faster to do the four comparisons of the point in rectangle check. Again if memory servers me, we don't really care what the distance from the origin is only if it is greater than the radius. So only partially perform the distance calculation, omitting the final square root, and compare against the square of the radius. Of course you still need to experiment and profile to make sure this bounding circle check is faster than just doing the regular point in rectangle check and you need to make sure you will have sufficient misses to offset the hits where you will end up doing both the bounding circle and rectangle checks.
You need to use a spatial index to find quickly in which rectangle the mouse is. I suggest a R-tree, here is the theorical part:
http://en.wikipedia.org/wiki/R-tree
And the c#,implementation:
http://sourceforge.net/projects/cspatialindexrt/
Create an rtee, add your rectangles then call the rtree.nearest method with the mouse coordinate to know the rectangles containing the mouse cursor. You can play with the distance parameter.
Hope it helps,
Anben Panglose.
I would go about dividing the display region into a quadrant.
Then place the rectangles into top-left, top-right, bottom-left, bottom-right grids.
Placing them means, creating a list for every quadrant and placing the rectangles in it.
Once the point is clicked, determine which quarter it belongs to and search in those rectangles only. This approach reduces your linear search by 4 times.
Remember that you need to also take care of overlapping where the point can belong to many rectangles. Here the z-order of your rectangles matter. So while the list is maintained for a quadrant, it should be sorted with it's z-order as a key.
Hope this helps.
May be something like this?
public bool isRectangelContainPoint(RectangleF rec, PointF pt)
{
if (pt.X >= rec.Left && pt.X <= rec.Right && pt.Y <= rec.Bottom && pt.Y >= rec.Top)
return true;
else
return false;
}
I generated this dendrogram using R's hclust(), as.dendrogram() and plot.dendrogram() functions.
I used the dendrapply() function and a local function to color leaves, which is working fine.
I have results from a statistical test that indicate if a set of nodes (e.g. the cluster of "_+v\_stat5a\_01_" and "_+v\_stat5b\_01_" in the lower-right corner of the tree) are significant or important.
I also have a local function that I can use with dendrapply() that finds the exact node in my dendrogram which contains significant leaves.
I would like to either (following the example):
Color the edges that join "_+v\_stat5a\_01_" and "_+v\_stat5b\_01_"; or,
Draw a rect() around "_+v\_stat5a\_01_" and "_+v\_stat5b\_01_"
I have the following local function (the details of the "nodes-in-leafList-match-nodes-in-clusterList" condition aren't important, but that it highlights significant nodes):
markSignificantClusters <<- function (n) {
if (!is.leaf(n)) {
a <- attributes(n)
leafList <- unlist(dendrapply(n, listLabels))
for (clusterIndex in 1:length(significantClustersList[[1]])) {
clusterList <- unlist(significantClustersList[[1]][clusterIndex])
if (nodes-in-leafList-match-nodes-in-clusterList) {
# I now have a node "n" that contains significant leaves, and
# I'd like to use a dendrapply() call to another local function
# which colors the edges that run down to the leaves; or, draw
# a rect() around the leaves
}
}
}
}
From within this if block, I have tried calling dendrapply(n, markEdges), but this did not work:
markEdges <<- function (n) {
a <- attributes(n)
attr(n, "edgePar") <- c(a$edgePar, list(lty=3, col="red"))
}
In my ideal example, the edges connecting "_+v\_stat5a\_01_" and "_+v\_stat5b\_01_" would be dashed and of a red color.
I have also tried using rect.hclust() within this if block:
ma <- match(leafList, orderedLabels)
rect.hclust(scoreClusterObj, h = a$height, x = c(min(ma), max(ma)), border = 2)
But the result does not work with horizontal dendrograms (i.e. dendrograms with horizontal labels). Here is an example (note the red stripe in the lower-right corner). Something is not correct about the dimensions of what rect.hclust() generates, and I don't know how it works, to be able to write my own version.
I appreciate any advice for getting edgePar or rect.hclust() to work properly, or to be able to write my own rect.hclust() equivalent.
UPDATE
Since asking this question, I used getAnywhere(rect.hclust()) to get the functional code that calculates parameters and draws the rect object. I wrote a custom version of this function to handle horizontal and vertical leaves, and call it with dendrapply().
However, there is some kind of clipping effect that removes part of the rect. For horizontal leaves (leaves that are drawn on the right side of the tree), the rightmost edge of the rect either disappears or is thinner than the border width of the other three sides of the rect. For vertical leaves (leaves that are drawn on the bottom of the tree), the bottommost edge of the rect suffers the same display problem.
What I had done as a means of marking significant clusters is to reduce the width of the rect such that I render a vertical red stripe between the tips of the cluster edges and the (horizontal) leaf labels.
This eliminates the clipping issue, but introduces another problem, in that the space between the cluster edge tips and the leaf labels is only six or so pixels wide, which I don't have much control over. This limits the width of the vertical stripe.
The worse problem is that the x-coordinate that marks where the vertical stripe can fit between the two elements will change based on the width of the larger tree (par["usr"]), which in turn depends on how the tree hierarchy ends up being structured.
I wrote a "correction" or, better termed, a hack to adjust this x value and the rect width for horizontal trees. It doesn't always work consistently, but for the trees I am making, it seems to keep from getting too close to (or overlapping) edges and labels.
Ultimately, a better fix would be to find out how to draw the rect so that there is no clipping. Or a consistent way to calculate the specific x position in between tree edges and labels for any given tree, so as to center and size the stripe properly.
I would also be very interested in a method for annotating edges with colors or line styles.
So you've actually asked about five questions (5 +/- 3). As far as writing your own rect.hclust like function, the source is in library/stats/R/identify.hclust.R if you want to look at it.
I took a quick glance at it myself and am not sure it does what I thought it did from reading your description--it seems to be drawing multiple rectangles, Also, the x selector appears to be hard coded to segregate the tags horizontally (which isn't what you want and there's no y).
I'll be back, but in the meantime you might (in addition to looking at the source) try doing multiple rect.hclust with different border= colors and different h= values to see if a failure pattern emerges.
Update
I haven't had much luck poking at this either.
One possible kludge for the clipping would be to pad the labels with trailing spaces and then bring the edge of your rectangle in slightly (the idea being that just bringing the rectangle in would get it out of the clipping zone but overwrite the ends of the labels).
Another idea would be to fill the rectangle with a translucent (low alpha) color, making a shaded area rather than a bounding box.