Three.js random mesh placement without overlap - javascript
I have a series of circles which are randomly positioned on the scene (x,y). I was wondering if anyone knew of a solution to make sure that when randomly placed, the circles would not overlap.
In your loop when you place circles, take the randomized (x,y) coordinate, and get the distance to all of the existing circles (another loop) --> √((x1-x2)^2 + (y1-y2)^2), if the distance is greater than the radii of both circles added together for EVERY circle, then you can place the circle, otherwise they overlap.
A statement checking to each circle's co-ordinates plus and minus its radius does not come within the co-ordinates of another circle plus and minus its radius in both the x and y direction could work
Related
Getting the coordinates of a point inside an overlapping rectangle
I have two colored rectangles, both being represented by a 2D array that directly corresponds to their coordinates(ex. [0][0] is the same as (0,0)). Things such as the width, height, and origin of each rectangle are known. As of now, I want their colors to "blend" in the area they intersect. Detecting if a point is within both rectangles is easy enough, and I have the point's coordinates relative to the origin of my first rectangle as it is the one I am iterating through for color blend checking. My problem is getting the point's coordinates relative to the second rectangle so I may get that rectangle's color at that point. Here is a visual example of what I mean. Visual representation of the problem. The black dot is a point on both Rect 1 and 2. Note that relative to the canvas, the top left corner of Rect 1 is always considered (0,0), and Rect 2 will always appear "on top" of Rect 1. My idea is to do a simple math equation to get the X and Y coordinates of the point on Rect 2, but so far it has not worked out.
Drawing a point to point ellipse to allow painting in GUI
I'm implementing some basic annotation draw features, such as arrows. Now I'm a little bit stuck with ellipse. The methods to draw an ellipse usually address using it's two diameters and eventually a rotation: However I want to display the ellipse between the point user clicked and the one he's hovering, therefore I need a function that calculates diameters and rotation based on two points: How would I do that? Can it be achieved with sufficient performance (as it renders during mouse-hovering)?
the steps you shoul follow: get the angle of the line (from this post: get angle of a line from horizon) rotate the canvas or at least the part you currently drawing (live demo here: http://www.html5canvastutorials.com/advanced/html5-canvas-transform-rotate-tutorial) draw an ellipse in canvas (http://www.scienceprimer.com/draw-oval-html5-canvas) the resulted ellipse will be transformed as described
It can be done in the same way that it is normally done, just using different math to calculate the shape. Without writing the entire code for you, you can start by having an event trigger when the user clicks the mouse button down. The function will copy the users x and y position based on the screen. Then there is a second function which will handle mouse movement. This function will keep track of the x and y coords of the mouse while it is in motion. The final function will be a mouse up event, when a user lifts their finger from the mouse button (assuming this is when the event should be finished). Using the initial and final position of the x and y coordinates, you can calculate the length of the line the user created. That line is the long diameter of the ellipse. Half this number for the large radius. Then use whatever ratio you are using to calculate the smaller radius from the larger one. Then create an ellipse based on these numbers. For the math: Suppose your first point is x1,y1 and the end point is x2,y2 I'm also assuming that we have a line going from bottom-left to top-right Distance between two points = sqrt((x2-x1)^2 + (y2-y1)^2) ---> (we will call this d1) half of this is the length of the large radius ---> (we will call this r1) Midpoint formula = ((x1+x2)/2 , (y1+y2)/2) ---> axis of rotation (we will call it (m1, m2)) distance from midpoint to end is just the radius radius is now the hypotenuse of constructed plane, y2-m2 is height of right triangle. Find the angles between midpoint and one end of larger radius - sin((y2-m2)/r1). Angle of smaller radius is this angle + pi/4 radians. calculate length of smaller radius based on ratio.
How to rotate div in circular motion while counter rotating inner circles?
This image is what I am trying to achieve. Circles on the edges are clickable. Its structure is made such that each rotation will be multiple of 45 deg. I am using css transform rotate property for rotation. How is it supposed to work? When we click on any circle on the edge it should come to its active position and it should always rotate in clockwise direction. Here is what I did I achieved rotation by assigning numbers to the circles. i.e., if clicked on 7 number then it will rotate by angle (9-7)*45=90 degrees. (This time I did not change the numbers dynamically. i.e., as the circle is rotating the numbers given to the circles are the same.) This works fine here. But, lets see this scenario: when we click on 2nd position circle it will rotate by 315 deg and then if you click again on the same (second) position then it will make the angle of 270 and it rotates the div in anti-clockwise direction. I think this is its behavior. But, I don't want this to happen. It should rotate again in clockwise direction and should take the active position. Now to achieve above I did this: Adding angle with prev angle. var prev_degree = prev_degree + current_degree; (current degree is being calculated using the same formula from above.) This time I changed numbers dynamically i.e., on each click numbers are given to the desired positions. Starting 1 as from Active position till 8 as shown in Image But this time, when I rotate circle 1, 2 times it rotates perfect then it starts working strange. If you are constantly clicking on the same number then it will add the same angle and will keep rotating perfect no matter what your angle is. If you click on random circles then it wont work which is totally wrong. Why clockwise? Because the circles on edges, they contain icon of which I have to maintain position when whole circle rotates.(I can achieve that rotating circles on the edges by assigning negative angles. But, now this is not a problem.) There is no case when I am getting negative angle. Let me know if you are not clear with my question. Please let me know your suggestions to make this work :-)
Show Extents Algorithm?
OH Great and Knowledgeable Stack Overflow, I humbly request your great minds assistance... I'm using the three js library, and I need to implement a 'show extents' button. It will move the camera to a position such that all the objects in the world are visible in the camera view (given they are not blocked of course). I can find the bounding box of all the objects in the world, say they are w0x,w0y,w0z and w1x,w1y,w1z How can I, given these to bounds, place the camera such that it will have a clear view of the edges of the box? Obviously there will have to be a 'side' chosen to view from...I've googled for an algorithm to no avail! Thanks!
So Let's say that you have picked a face. and that you are picking a camera position so that the camera's line-of-sight is parallel to one of the axes. Let's say that the face has a certain width, "w", and let's say that your camera has a horizontal field-of-view "a". What you want to figure out is what is the distance, "d" from the center of the face that the camera should be to see the whole width. If you draw it out you will see that you basically have an isosceles triangle whose base is length w and with the angle a at the apex. Not only that but the angle bisector of the apex angle forms two identical right triangles and it's length (to the base) is the distance we need to figure out. Trig tells us that the tangent of an angle is the ratio of the oposite and adjacent sides of the triangle. So tan(a/2) = (w/2) / d simplifying to: d = w / 2*tan(a/2) So if you are placing the camera some axis-aligned distance from one of your bounding box faces then you just need to move d distance along the axis of choice. Some caveats, make sure you are using radians for the javascript trig function input. Also you may have to compute this again for your face height and camera's vertical field-of-view and pick the farther distance if your face is not square. If you want to fit the bounding box from an arbitrary angle you can use the same ideas - but first you have to find the (aligned) bounding box of the scene projected onto a plane perpendicular to the camera's line of sight
Move rectangles so they don't overlap
This is a half programming, half math question. I've got some boxes, which are represented as four corner points. They are true rectangles, the intersections of two sets of parallel lines, with every line in each set at a right angle to both lines in the other set (just so we're clear.) For any set of n boxes, how can I efficiently calculate where to move them (the least distance) so that they do not overlap each other? I'm working in javascript here. Here's the data: //an array of indefinite length of boxes //boxes represented as arrays of four points //points represented as arrays of two things, an x and a y, measured in //pixels from the upper left corner var boxes = [[[504.36100124308336,110.58685958804978],[916.3610012430834,110.58685958804978],[916.3610012430834,149.58685958804978],[504.36100124308336,149.58685958804978]],[[504.4114378910622,312.3334473005064],[554.4114378910622,312.3334473005064],[554.4114378910622,396.3334473005064],[504.4114378910622,396.3334473005064]],[[479.4272869132357,343.82042608058134],[516.4272869132358,343.82042608058134],[516.4272869132358,427.82042608058134],[479.4272869132357,427.82042608058134]],[[345.0558946408693,400.12499171846],[632.0558946408694,400.12499171846],[632.0558946408694,439.12499171846],[345.0558946408693,439.12499171846]],[[164.54073131913765,374.02074227992966],[264.54073131913765,374.02074227992966],[264.54073131913765,428.02074227992966],[164.54073131913765,428.02074227992966]],[[89.76601656567325,257.7956256799442],[176.76601656567325,257.7956256799442],[176.76601656567325,311.7956256799442],[89.76601656567325,311.7956256799442]],[[60.711850703535845,103.10558195262593],[185.71185070353584,103.10558195262593],[185.71185070353584,157.10558195262593],[60.711850703535845,157.10558195262593]],[[169.5240557746245,23.743626531766495],[231.5240557746245,23.743626531766495],[231.5240557746245,92.7436265317665],[169.5240557746245,92.7436265317665]],[[241.6776988694169,24.30106373152889],[278.6776988694169,24.30106373152889],[278.6776988694169,63.30106373152889],[241.6776988694169,63.30106373152889]],[[272.7734457459479,15.53275710947554],[305.7734457459479,15.53275710947554],[305.7734457459479,54.53275710947554],[272.7734457459479,54.53275710947554]],[[304.2905062327675,-3.9599943474960035],[341.2905062327675,-3.9599943474960035],[341.2905062327675,50.04000565250399],[304.2905062327675,50.04000565250399]],[[334.86335590542114,12.526345270766143],[367.86335590542114,12.526345270766143],[367.86335590542114,51.52634527076614],[334.86335590542114,51.52634527076614]],[[504.36100124308336,110.58685958804978],[916.3610012430834,110.58685958804978],[916.3610012430834,149.58685958804978],[504.36100124308336,149.58685958804978]],[[504.4114378910622,312.3334473005064],[554.4114378910622,312.3334473005064],[554.4114378910622,396.3334473005064],[504.4114378910622,396.3334473005064]],[[479.4272869132357,343.82042608058134],[516.4272869132358,343.82042608058134],[516.4272869132358,427.82042608058134],[479.4272869132357,427.82042608058134]],[[345.0558946408693,400.12499171846],[632.0558946408694,400.12499171846],[632.0558946408694,439.12499171846],[345.0558946408693,439.12499171846]],[[164.54073131913765,374.02074227992966],[264.54073131913765,374.02074227992966],[264.54073131913765,428.02074227992966],[164.54073131913765,428.02074227992966]],[[89.76601656567325,257.7956256799442],[176.76601656567325,257.7956256799442],[176.76601656567325,311.7956256799442],[89.76601656567325,311.7956256799442]],[[60.711850703535845,103.10558195262593],[185.71185070353584,103.10558195262593],[185.71185070353584,157.10558195262593],[60.711850703535845,157.10558195262593]],[[169.5240557746245,23.743626531766495],[231.5240557746245,23.743626531766495],[231.5240557746245,92.7436265317665],[169.5240557746245,92.7436265317665]],[[241.6776988694169,24.30106373152889],[278.6776988694169,24.30106373152889],[278.6776988694169,63.30106373152889],[241.6776988694169,63.30106373152889]],[[272.7734457459479,15.53275710947554],[305.7734457459479,15.53275710947554],[305.7734457459479,54.53275710947554],[272.7734457459479,54.53275710947554]],[[304.2905062327675,-3.9599943474960035],[341.2905062327675,-3.9599943474960035],[341.2905062327675,50.04000565250399],[304.2905062327675,50.04000565250399]],[[334.86335590542114,12.526345270766143],[367.86335590542114,12.526345270766143],[367.86335590542114,51.52634527076614],[334.86335590542114,51.52634527076614]]] This fiddle shows the boxes drawn on a canvas semi-transparently for clarity.
You could use a greedy algorithm. It will be far from optimal, but may be "good enough". Here is a sketch: 1 Sort the rectangles by the x-axis, topmost first. (n log n) 2 for each rectangle r1, top to bottom //check for intersections with the rectangles below it. // you only have to check the first few b/c they are sorted 3 for every other rectangle r2 that might intersect with it 4 if r1 and r2 intersect //this part is easy, see #Jose's answer 5 left = the amount needed to resolve the collision by moving r2 left 6 right = the amount needed to resolve the collision by moving r2 right 7 down = the amount needed to resolve the collision by moving r2 down 8 move r2 according to the minimum value of (left, right down) // (this may create new collisions, they will be resolved in later steps) 9 end if 10 end 11 end Note step 8 could create a new collision with a prior rectangle, which wouldn't be resolved properly. Hm. You may need to carry around some metadata about previous rectangles to avoid this. Thinking...
Keep in mind the box model, given any two rectangles you have to calculate the two boxes width and height, adding their respective margins, paddings, and borders (add the left/right of them to detect collision on the x axis, and top/bottom to detect collision on the y axis), then you can calculate the distance between element 1 and 2 adding the result to their respective coordinate position, for example ((positionX2+totalWidth2) - (positionX1+totalWidth1)) to calculate collision along the X axis. If it is negative, they are overlapping. Once you know this, if they won't overlap by moving them, you can move them normally, otherwise you have to subtract the amount of space they are overlapping from the value you want to move them. Since the environment is a 2D plane, this should be pretty straightforward. With a library such as jQuery would be a joke, but even in plain js is just basic addiction and subtraction.
Assuming the boxes are aligned to the x and y axis as in your comment, first I'd change the representation of each rectangle to 4 points: top, right, bottom, left and store them as points on the rectangle. Second, let's simplify the problem to "Given n rectangles, where is the nearest point where rectangle r can move to so that it doesn't overlap any other rectangles"? That simplifies the problem a great deal, but also should provide a decent solution. Thus, we have our function: function deOverlapTheHonkOuttaTheRectangle(rectangle, otherRectangles){ .. } Now, each other rectangle will disallow a certain range of motion for the original rectangle. Thus, you calculate all of these disallowed moves. From these, you can calculate the disallow shape that overlaps the origin and each other. For example, lets say rect1 disallows a shift of -3px to 5px right and 4px to 10px up, and rect2 disallows -4px to 1px right and -2px to 5px up. rect1 was not considered until rect2 came along, since that one overlaps the origin and rect1. Starting with rect2, you'd have [[-4, -2],[1,-2],[1,5],[-4,5]]. Figuring in rect1 gives [[-4, -2],[1,-2],[1,4],[5,4],[5,10],[-3,10],[-3,5],[-4,5]] (see image below for clarification). You keep building these up for each overlapping disallowed rectangle. Once you have considered all the rectangles, then you can use a distance formula from the origin to get the smallest distance you can move your rectangle and move it. Finally, you repeat this process for all remaining rectangles.