Set of tiles - calculate outline path - math

Problem (psuedo)
How to find the outline of a set of tiles? Let's assume we have three tiles, at the x/y coordinates A[20,20], B[20,30] and C[30,30] (this will make a simple L-shape).
Those points represent the centers of the tiles.
Each tile has 4 vertexes: TL (top left), TR, BL (bottom left) and BR.
Together, the 3 tiles have 8 unique (non-overlapping) vertexes.
We want the red line (path), defined by green dots (vertexes):
http://img7.imageshack.us/img7/2469/lshapetiles.png
Needed solution The output of the algorithm should be a path that forms the outline shape of the tiles, consisting out of these vertexes - in this order:
A TL, A TR, A BR, C TR, C BR, C BL, B BL, B TL (and optional, A TL again, to close).
See the red line.
Possible solution(s)
One option is to iterate over all the tiles, and for each tile check:
+ does it have a neighbor above? If not, at TL and TR to path
+ does it have a neighbor on the right? If not, at TR and BR to path
+ does it have a neighbor underneath? If not, at BL and BR to path
+ does it have a neighbor on the left? If not, at TL and BL to path
If you only add the found vertexes to the path if they're not added already yet, you've succesfully collected the unique vertexes for the path.
However, they might be in the wrong order. This is a (the) problem.
Does someone know of a good solution (algorithm) for this?

First, build a data structure to represent the tile structure.
Algorithm:
1 find the top-left point.
2 start from this point, iteratively find the next point by using the up, right,down,left order (in the data structure, each point contains these 4 links)
3 stop when go back the initial point.
if the graph contains separated structures, run the above algorithm for each connected component.

You can try something like this:
You iteratively build a graph representing the tiles, except for a small change -when an edge is doubled, you remove it.
So you add the first tile to the graph G, all its edges will be added. For the next tile, you add all its edges to G, but if any of its edges overlap with an edge in G, you remove that edge from G. You continue this process for all tiles.
At the end, you will only be left with "outside" edges, so you just traverse the path you have left.

Related

Creating a network graph with set node positions and concentrated edges with both circleheads and arrowheads in R

I've been trying to find a way to replicate the following network graph format in R using DiagrammeR/GraphViz, but without success (ignore the thick black arrow on N1): https://i.stack.imgur.com/oHpQz.png
The graph is a directed graph and each edge in a certain direction either ends with an arrowhead (-->) if the edge value is positive, or a circle/odot (--o) if the edge value is negative. Between a pair of nodes (ex. N1 -- A1), there can be an edge N1 --> A1 and an edge A1 --o N1, and these need to be concentrated so that the two edges look like one line with an arrowhead on one end and a circlehead on the opposite end (like this: o--->). These cannot be parallel or look like two edges ideally.
Another requirement is that the nodes have to be in very specific positions and remain there throughout model simulations where edges might change. From what I have tried and the documentation I have read, this is not possible to do in DOT format, but is possible in neato format.
This is where I get a problem. In neato, I can align the nodes exactly where I want them by defining their x,y positions. However, when I use concentrate = true to create the o---> edge from two otherwise parallel edges, only one type of arrowhead remains. So an edge that's supposed to look like o---> ends up looking like ---> or o---.
This is not a problem in DOT format as concentrate = true does what I want it to do, but in DOT I cannot assign exact node positions. I have tried getting around this using node ranks but without much luck. It seems to stack nodes I want in different ranks within the same rank. As well, concentrate = true doesn't seem to work for edges between nodes within the same rank, as it leaves them as two separate curved edges ---> and o--- without concentrating them.
The reason why I need this to work is because I'm running model simulations where the edges change, and I need to generate hundreds of such graphs. For easy comparison, the nodes need to stay in the same place for consistency.
This is the closest I could come up with using neato format (nodes are positioned the way I want but it's not showing the proper o---> for all the black edges minus self-edges; red edges are true one-way links): https://i.stack.imgur.com/YJBY7.jpg
If only the edges showed up as the proper o---> format, this would be perfect for my needs. If you know of any way to fix this issue using DiagrammeR/GraphViz, or even another program, I would be so grateful. Thanks!
You probably don't need concentrate. Look at arrowtail and dir (https://www.graphviz.org/doc/info/attrs.html#d:arrowtail and https://www.graphviz.org/doc/info/attrs.html#d:dir) and neato -n
digraph c {
graph[label="can neato do the work?"]
node[shape=circle]
a [pos="100,100"]
b [pos="200,100"]
c [pos="300,100"]
a->b [dir=both arrowtail=odot]
c->c [dir=both arrowtail=odot arrowhead=none]
}
Giving:

Get Edges between Vertices (outer polygon)

I'm using THREE.JS and I have a this mesh with different surfaces. Of each surface I got its vertices. Now I want to create edges ( connect the vertices with lines). The vertices are in an arbitrary order, so I can't simply connect v1 with v2, v2 with v3 and so on. I think I have to walk through them with a ray clockwise or counter clockwise and put them in the right order somehow and I have to somehow check their distances, so that the horizontal line between the inner vertices doesn't appear, rather it should go right along the real edges,but I don't know how... Any idea?
(the spheres are the vertices that are the real corners of the surface, the orange lines are the wrong edges that need to be corrected and the blue lines are the edges of each single face)
I need to create these 8 edges (red)
Assuming that you are able to assign a unique number to the vertices and to uniquely associate every triangle to a face, and that the triangulation is watertight, the edges of a face are those edges that are common to a triangle of that face and a triangle of another. When you have all edges of a face, it is a trivial matter to chain them in a polygon.

Determining whether an object is in the path of two other objects in 2D space

Say there are 3 objects defined by rectangles in x-y coordinates. The rectangles can be of any orientation (not necessarily parallel to the axes).
How would you go about approaching the problem of determining whether object C is partially, fully, or not at all obscured by object B from the perspective of object A (object A can see from anywhere on its rectangle)?
Second question: is it possible to determine the percentage of object C that is visible?
Here is my (completely untested) approach.
Consider first the same problem but only looking from one fixed point P.
Find the two (infinite) lines that go through P and enclose your rectangle B. Since it is a rectangle these two lines will be two of the four lines that go through P and each vertex of B.
Check whether each vertex of C is in between these two lines or not. If any vertex of C is between these two lines check whether it is closer or farther from P than B is. If it is farther than B is at least partially obscuring C.
Now do this for each vertex of A. You may get more complicated results if you see a part of C from one point P in A and a different part of C from a different point P in A. I will leave it up to you how to deal with that.
To determine the percent coverage, compute the shape that you get from intersecting rectangle C with these two lines and compute its area, then divide by the total area of the shape.
I have left all the math in this up to you to figure out, but if you have any specific questions about your work, feel free to ask those.
This answer would benefit nicely from having some pictures added, but I'm hoping you can understand this answer while drawing your own diagrams according to the steps provided.

Dividing space outside of convex polygons into horizontally spanning quadrilaterals

I'm looking for an algorithm that can take an area containing a set of non-overlapping convex polygons as input, and break the space outside of the polygons into a set of non-overlapping convex quadrilaterals. The quadrilaterals need to have the property that they (individually) use as much horizontal space as possible.
Here's the input:
Here's the desired output:
I feel like I have seen some variation of this algorithm used to calculate regions to be flood-filled in very old paint programs. Is there a pleasant way to do this in better than O(n^2) time?
Edit: I realize there are some triangles in the output. I should probably state that quadrilaterals are the desired output, falling back to triangles only when it's physically impossible to use a quad.
I came up with a solution to this. In order to solve this efficiently, some sort of spatial data structure is needed in order to query which polygons are overlapped by a given rectangular area. I used a Quadtree. It's also necessary for the polygon data structure being used to be able to distinguish between internal and external edges. An edge is internal if it is common to two polygons.
The steps are as follows (assuming a coordinate system with the origin in the top-left corner):
Insert all polygons into whatever spatial data structure you're using.
Iterate over all polygons and build a list of all of the Y values upon
which vertices occur. This has the effect of conceptually dividing up
the scene into horizontal strips:
Iterate over the pairs of Y values from top to bottom. For each
pair (y0, y1) of Y values, declare a rectangular area a with
the the top left corner (0, y0) and bottom right corner
(width, y1). Determine the set of polygons S that are
overlapped by a by querying the spatial data structure. For
each polygon p in S, determine the set of edges E of p
that are overlapped by a. For best results, ignore any edge in
E with a normal that points directly up or down. For each
edge e in E, it's then necessary to determine the pair of
points at which e intersects the top and bottom edges of a.
This is achieved with a simple line intersection test,
treating the top and bottom edges of a as simple horizontal
line segments. Join the intersection points to create a set of
new line segments, shown in red:
Create vertical line segments L0 = (0, y0) → (0, y1) and
L1 = (width, y0) → (width, y1). Working from left to right,
gather any line segments created in the preceding step into pairs,
ignoring any line segments that were created from internal edges.
If there were no intersecting external edges, then the only two
edges will be L0 and L1. In this example strip, only four
edges remain:
Join the vertices in the remaining pairs of edges to create
polygons:
Repeating the above process for each horizontal strip achieves
the desired result. Assuming a set of convex, non-overlapping
polygons as input, the created polygons are guaranteed to be
either triangles or quadrilaterals. If a horizontal strip contains
no edges, the algorithm will create a single rectangle. If no
polygons exist in the scene, the algorithm will create a single
rectangle covering the whole scene.

How to calculate a point on a circle knowing the radius and center point

I have a complicated problem and it involves an understanding of Maths I'm not confident with.
Some slight context may help. I'm building a 3D train simulator for children and it will run in the browser using WebGL. I'm trying to create a network of points to place the track assets (see image) and provide reference for the train to move along.
To help explain my problem I have created a visual representation as I am a designer who can script and not really a programmer or a mathematician:
Basically, I have 3 shapes (Figs. A, B & C) and although they have width, can be represented as a straight line for A and curves (B & C). Curves B & C are derived (bend modified) from A so are all the same length (l) which is 112. The curves (B & C) each have a radius (r) of 285.5 and the (a) angle they were bent at was 22.5°.
Each shape (A, B & C) has a registration point (start point) illustrated by the centre of the green boxes attached to each of them.
What I am trying to do is create a network of "track" starting at 0, 0 (using standard Cartesian coordinates).
My problem is where to place the next element after a curve. If it were straight track then there is no problem as I can use the length as a constant offset along the y axis but that would be boring so I need to add curves.
Fig. D. demonstrates an example of a possible track layout but please understand that I am not looking for a static answer (based on where everything is positioned in the image), I need a formula that can be applied no matter how I configure the track.
Using Fig. D. I tried to work out where to place the second curved element after the first one. I used the formula for plotting a point of the circumference of a circle given its centre coordinates and radius (Fig. E.).
I had point 1 as that was simply a case of setting the length (y position) of the straight line. I could easily work out the centre of the circle because that's just the offset y position, the offset of the radius (r) (x position) and the angle (a) which is always 22.5° (which, incidentally, was converted to Radians as per formula requirements).
After passing the values through the formula I didn't get the correct result because the formula assumed I was working anti-clockwise starting at 3 o'clock so I had to deduct 180 from (a) and convert that to Radians to get the expected result.
That did work and if I wanted to create a 180° track curve I could use the same centre point and simply deducted 22.5° from the angle each time. Great. But I want a more dynamic track layout like in Figs. D & E.
So, how would I go about working point 5 in Fig. E. because that represents the centre point for that curve segment? I simply have no idea.
Also, as a bonus question, is this the correct way to be doing this or am I over-complicating things?
This problem is the only issue stopping me from building my game and, as you can appreciate, it is a bit of a biggie so I thank anyone for their contribution in advance.
As you build up the track, the position of the next piece of track to be placed needs to be relative to location and direction of the current end of the track.
I would store an (x,y) position and an angle a to indicate the current point (with x,y starting at 0, and a starting at pi/2 radians, which corresponds to straight up in the "anticlockwise from 3-o'clock" system).
Then construct
fx = cos(a);
fy = sin(a);
lx = -sin(a);
ly = cos(a);
which correspond to the x and y components of 'forward' and 'left' vectors relative to the direction we are currently facing. If we wanted to move our position one unit forward, we would increment (x,y) by (fx, fy).
In your case, the rule for placing a straight section of track is then:
x=x+112*fx
y=y+112*fy
The rule for placing a curve is slightly more complex. For a curve turning right, we need to move forward 112*sin(22.5°), then side-step right 112*(1-cos(22.5°), then turn clockwise by 22.5°. In code,
x=x+285.206*sin(22.5*pi/180)*fx // Move forward
y=y+285.206*sin(22.5*pi/180)*fy
x=x+285.206*(1-cos(22.5*pi/180))*(-lx) // Side-step right
y=y+285.206*(1-cos(22.5*pi/180))*(-ly)
a=a-22.5*pi/180 // Turn to face new direction
Turning left is just like turning right, but with a negative angle.
To place the subsequent pieces, just run this procedure again, calculating fx,fy, lx and ly with the now-updated value of a, and then incrementing x and y depending on what type of track piece is next.
There is one other point that you might consider; in my experience, building tracks which form closed loops with these sort of pieces usually works if you stick to making 90° turns or rather symmetric layouts. However, it's quite easy to make tracks which don't quite join up, and it's not obvious to see how they should be modified to allow them to join. Something to bear in mind perhaps if your program allows children to design their own layouts.
Point 5 is equidistant from 3 as 2, but in the opposite direction.

Resources