Browse Source

Insideness parser should work correctly now...

Joeri Exelmans 2 years ago
parent
commit
4988fd3eb5
1 changed files with 42 additions and 21 deletions
  1. 42 21
      src/parser/trivial_parser.ts

+ 42 - 21
src/parser/trivial_parser.ts

@@ -198,6 +198,39 @@ export class TrivialParser  {
               const updatedSurface = updatedGeometry.w * updatedGeometry.h;
               const updatedAsNode = findCorrespondingAsNode(corrState.nodes.get(updatedNodeId) as INodeState);
 
+              const findAndSetNewParent = (geometry: Geometry2DRect, asNodeState: INodeState) => {
+                const surface = geometry.w * geometry.h;
+                // Of all other geometries that we are inside of, find the one with the smallest surface area.
+                // This will be our new parent.
+                let smallestParent: INodeState | null = null;
+                let smallestSurface = Infinity;
+                for (const [otherNodeId,otherNodeState] of sourceState.nodes.entries()) {
+                  if (otherNodeState.creation === edgeCreation.source) {
+                    continue; // don't compare with ourselves
+                  }
+                  const otherGeometry = getGeometry(otherNodeId);
+                  if (otherGeometry !== undefined) {
+                    const inside = isInside(geometry, otherGeometry);
+                    if (inside) {
+                      const surface = otherGeometry.w * otherGeometry.h;
+                      if (surface < smallestSurface) {
+                        smallestSurface = surface;
+                        smallestParent = findCorrespondingAsNode(corrState.nodes.get(otherNodeId) as INodeState);
+                      }
+                    }
+                  }
+                }
+                if (smallestParent !== null) {
+                  const existingLink = asNodeState.getOutgoingEdges().get("hasParent");
+                  if (existingLink !== smallestParent) {
+                    console.log("updated geometry is on inside...");
+                    const asParentLink = asNodeState.getDeltasForSetEdge(this.primitiveRegistry, "hasParent", smallestParent.asTarget());
+                    applyToState(corrState, asParentLink);
+                    targetDeltas.push(...asParentLink);
+                  }
+                }
+              }
+
               // 1. Check if existing parent links still hold
               // 1.a. outgoing parent links
               const otherAsNodeState = updatedAsNode.getOutgoingEdges().get("hasParent");
@@ -219,7 +252,10 @@ export class TrivialParser  {
                 const otherCsNodeState = findCorrespondingAsNode(otherAsNodeState, true);
                 const otherNodeId = otherCsNodeState.creation.id.value;
                 const otherGeometry = getGeometry(otherNodeId);
-                if (otherGeometry === undefined || !isInside(otherGeometry, updatedGeometry)) {
+                if (otherGeometry === undefined) {
+                  throw new Error("Assertion failed: The Corresponding CS node of an AS node that is target of 'hasParent' has no geometry.");
+                }
+                if (!isInside(otherGeometry, updatedGeometry)) {
                   // parent relation no longer holds
                   const otherAsNode = findCorrespondingAsNode(corrState.nodes.get(otherNodeId) as INodeState);
                   console.log("deleting incoming link...")
@@ -227,27 +263,21 @@ export class TrivialParser  {
                   const deleteLink = otherAsNode.getDeltasForSetEdge(this.primitiveRegistry, "hasParent", null); // deletes the edge
                   applyToState(corrState, deleteLink);
                   targetDeltas.push(...deleteLink);
+                  // Find new parent of otherAsNode:
+                  findAndSetNewParent(otherGeometry, otherAsNode);
+                  // The above function call leads to time complexity O(n^2) for parsing.
+                  // There should be ways to make it more efficient (e.g., keeping all rountangles sorted by their surface area, in order to find the new parent much quicker), but for our demonstrator, the bottleneck is React/d3, not the parsing/rendering process.
                 }
               }
 
               // 2. Compare the new geometry to every other rountangle
-              let smallestParent: INodeState | null = null;
-              let smallestSurface = Infinity;
               for (const [otherNodeId,otherNodeState] of sourceState.nodes.entries()) {
                 if (otherNodeState.creation === edgeCreation.source) {
                   continue; // don't compare with ourselves
                 }
                 const otherGeometry = getGeometry(otherNodeId);
                 if (otherGeometry !== undefined) {
-                  const inside = isInside(updatedGeometry, otherGeometry);
-                  // CORRECT: For geometries that the updated geometry is inside of, we are only interested in the smallest of them:
-                  if (inside) {
-                    const surface = otherGeometry.w * otherGeometry.h;
-                    if (surface < smallestSurface) {
-                      smallestSurface = surface;
-                      smallestParent = findCorrespondingAsNode(corrState.nodes.get(otherNodeId) as INodeState);
-                    }
-                  }
+                  findAndSetNewParent(updatedGeometry, updatedAsNode);
                   const outside = isInside(otherGeometry, updatedGeometry);
                   // CORRECT: For geometries that are inside of our updated geometry, we should only "steal" their outgoing parent link if our updated geometry is smaller than their current parent.
                   if (outside) {
@@ -274,15 +304,6 @@ export class TrivialParser  {
                   }
                 }
               }
-              if (smallestParent !== null) {
-                const existingLink = updatedAsNode.getOutgoingEdges().get("hasParent");
-                if (existingLink !== smallestParent) {
-                  console.log("updated geometry is on inside...");
-                  const asParentLink = updatedAsNode.getDeltasForSetEdge(this.primitiveRegistry, "hasParent", smallestParent.asTarget());
-                  applyToState(corrState, asParentLink);
-                  targetDeltas.push(...asParentLink);
-                }
-              }
             }
           }
         }