0

I'm working on a procedural city building project that uses a half-edge/doubly connected edge list data structure to represent roads. In the image below, the pre-existing connections are solid lines. There are two half-edge links: A to B and X to Y. I need to insert a new connection (dashed line) which is comprised of two new half-edges: 1 and 2. The arrows represent the direction of the half-edge in question, with the closest node (solid circles) being where that half-edge starts from.

I need to programmatically determine whether to split the half-edge link AB or XY. In this situation, link AB should be split creating two new half-edge links: A1 and 2B. How would you go about determining this?

enter image description here

Edvard-D
  • 384
  • 1
  • 6
  • 17
  • Sorry, I don’t understand the question. You don’t explain why you would want to split AB or XY. What is wrong with the dashed line as the new half edge ? Your question doesn’t make any sense – chmike Jan 15 '20 at 13:29
  • @chmike Sorry, to clarify, when you're creating a half-edge one piece of information you need to store is the next half-edge. Starting out, the A half-edge stores a reference to the B half-edge since B is the next one in the link. When I insert the new connection I need to change that reference from B to 1, since A now links to half-edge 1. Half-edge 2 will now be the half-edge that stores a reference to B. The problem is that there's no easy way to tell (that I know of) that the links should be A1/2B rather than X1/2Y. – Edvard-D Jan 15 '20 at 18:05
  • I still don't understand and can't help you. There are still a lot of missing information like the constrains that must be satisfied that could help to determine what is not valid or what is the right answer. I doubt that somebody can help you. The problem is not clear enough – chmike Jan 15 '20 at 18:18
  • @chmike I'm trying to think of what information I might've left out. I guess another important factor about half-edges is that the links must be clockwise. A1, 2B, XY are all valid links since their direction is clockwise. X1/2Y are not valid since they go counter clockwise. – Edvard-D Jan 15 '20 at 18:25

1 Answers1

0

I think I've got a solution. The reason links X1/2Y aren't valid is that they cross over each other when you draw the links from start to finish. That got me thinking that testing for intersection should work.

The first step to doing this is finding the "creation vector" of the new connection that's being made (the dashed line). In this case, node2 is the startPosition, with the endPosition being the center node. This is done as follows:

creationVector = normalize(endPosition - startPosition);

Next, you need to calculate two points related to node2 in the diagram: the incomingPoint and outgoingPoint. To maintain the clockwise direction, incomingPoint needs to be to the left of the creation vector and the outgoingPoint needs to be to the right. In the diagrams below incomingPoint is red while outgoingPoint is blue. This is done as follows:

incomingPoint = nodeAPosition + new float2(-creationVector.y, creationVector.x);
outgoingPoint = nodeAPosition + new float2(creationVector.y, -creationVector.x);

The last bit is drawing two lines and testing whether there's an intersection between them. We'll start with the invalid links, X1/2Y. In this case, the two lines we're drawing are: nodeX to incomingPoint, and outgoingPoint to nodeA. The solution I found for testing for intersection comes from this blog post. I'll include my version below for completeness:

private float2 IntersectionPointGet(
        float2 a1,
        float2 a2,
        float2 b1,
        float2 b2,
        out bool isIntersection)
{
    float tmp = (b2.x - b1.x) * (a2.y - a1.y) - (b2.y - b1.y) * (a2.x - a1.x);

    if (tmp == 0)
    {
        isIntersection = false;
        return float2.zero;
    }

    float mu = ((a1.x - b1.x) * (a2.y - a1.y) - (a1.y - b1.y) * (a2.x - a1.x)) / tmp;

    isIntersection = true;
    return new float2(
        b1.x + (b2.x - b1.x) * mu,
        b1.y + (b2.y - b1.y) * mu
    );
}

As you can see, links X1/2Y intersect and thus are invalid: enter image description here

Now compare this to A1/2B, which do not intersect and thus are valid: enter image description here

The nice thing about this solution is that you only need to test one link pair. If X1/2Y is invalid, we can assume A1/2B is valid. That means that link AB is the one that needs to be split, while link XY should be left alone.

Edvard-D
  • 384
  • 1
  • 6
  • 17