Skip to content

Commit

Permalink
Added Backdrop Node for Meshroom graph
Browse files Browse the repository at this point in the history
Nodes now have a size defined

Added the notion of Region in a graph
  • Loading branch information
Vivek VERMA authored and Vivek VERMA committed Oct 21, 2024
1 parent 88f9d4b commit f660d83
Show file tree
Hide file tree
Showing 8 changed files with 558 additions and 21 deletions.
78 changes: 78 additions & 0 deletions meshroom/core/desc.py
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,22 @@ class Node(object):
value="",
invalidate=False,
),
FloatParam(
name="nodeWidth",
label="Node Width",
description="The Node's Width.",
value=160,
range=None,
enabled=False # Hidden always
),
FloatParam(
name="nodeHeight",
label="Node Height",
description="The Node's Height.",
value=120,
range=None,
enabled=False # Hidden always
),
ColorParam(
name="color",
label="Color",
Expand Down Expand Up @@ -779,6 +795,68 @@ def __init__(self):
def processChunk(self, chunk):
pass

def stopProcess(self, chunk):
pass


class Backdrop(InputNode):
""" A Backdrop for other nodes.
"""

# The internal inputs' of Backdrop Node needs a Integer Field to determine the font size for the comment
internalInputs = [
StringParam(
name="invalidation",
label="Invalidation Message",
description="A message that will invalidate the node's output folder.\n"
"This is useful for development, we can invalidate the output of the node when we modify the code.\n"
"It is displayed in bold font in the invalidation/comment messages tooltip.",
value="",
semantic="multiline",
advanced=True,
uidIgnoreValue="", # If the invalidation string is empty, it does not participate to the node's UID
),
StringParam(
name="comment",
label="Comments",
description="User comments describing this specific node instance.\n"
"It is displayed in regular font in the invalidation/comment messages tooltip.",
value="",
semantic="multiline",
invalidate=False,
),
IntParam(
name="fontSize",
label="Font Size",
description="The Font size for the User Comment on the Backdrop.",
value=12,
range=(6, 100, 1),
),
FloatParam(
name="nodeWidth",
label="Node Width",
description="The Backdrop Node's Width.",
value=600,
range=None,
enabled=False # Hidden always
),
FloatParam(
name="nodeHeight",
label="Node Height",
description="The Backdrop Node's Height.",
value=400,
range=None,
enabled=False # Hidden always
),
ColorParam(
name="color",
label="Color",
description="Custom color for the node (SVG name or hexadecimal code).",
value="",
invalidate=False,
)
]


class CommandLineNode(Node):
"""
Expand Down
149 changes: 148 additions & 1 deletion meshroom/core/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from meshroom.core import Version
from meshroom.core.attribute import Attribute, ListAttribute, GroupAttribute
from meshroom.core.exception import StopGraphVisit, StopBranchVisit
from meshroom.core.node import nodeFactory, Status, Node, CompatibilityNode
from meshroom.core.node import nodeFactory, Status, Node, CompatibilityNode, Position

# Replace default encoder to support Enums

Expand Down Expand Up @@ -56,6 +56,130 @@ def GraphModification(graph):
graph.updateEnabled = enabled


class Region:
""" Defines the boundaries for a Region on the 2d Plane (Graph in our Context).
"""

class Range:
""" Defines a Range between two points in the Graph or 2d Plane, inclusive of the 2nd Point.
"""

def __init__(self, x, y):
""" Constructor.
Args:
x (int | float): An integer or float start.
y (int | float): An integer or float end.
"""
# Internal Coords
self._x = x
self._y = y

def __repr__(self):
""" Represents the instance.
"""
return f"Range::{self._x}, {self._y}"

def __contains__(self, _i):
""" Returns True if the provided integer or float falls between the start and the end point of the range.
"""
return self._x < _i <= self._y


def __init__(self, x=0, y=0, right=0, bottom=0):
""" Constructor.
Args:
x (int | float): The x coordinate of the top-left point on the Region.
y (int | float): The y coordinate of the top-left point on the Region.
right (int | float): The x coordinate of the bottom-right point on the Region.
bottom (int | float): The y coordinate of the bottom-right point on the Region.
"""
# The coords of the Region can be represented as
# (x, y)
# .------------------------.
# | |
# | |
# | |
# | |
# '------------------------'
# (right, bottom)
self._x = x
self._y = y
self._right = right
self._bottom = bottom

# Properties
x = property(lambda self: self._x)

Check notice on line 113 in meshroom/core/graph.py

View check run for this annotation

codefactor.io / CodeFactor

meshroom/core/graph.py#L113

Multiple spaces before operator. (E221)
y = property(lambda self: self._y)

Check notice on line 114 in meshroom/core/graph.py

View check run for this annotation

codefactor.io / CodeFactor

meshroom/core/graph.py#L114

Multiple spaces before operator. (E221)
right = property(lambda self: self._right)

Check notice on line 115 in meshroom/core/graph.py

View check run for this annotation

codefactor.io / CodeFactor

meshroom/core/graph.py#L115

Multiple spaces before operator. (E221)
bottom = property(lambda self: self._bottom)

Check notice on line 116 in meshroom/core/graph.py

View check run for this annotation

codefactor.io / CodeFactor

meshroom/core/graph.py#L116

Multiple spaces before operator. (E221)

def __contains__(self, point):
""" Returns True if the provided Point is present in the Region.
"""
return self.contains(point)

def __repr__(self):
""" Represents the instance.
"""
return f"Region::{self.points()}"

# Public
def xrange(self):
""" Defines the Range between the left most and right most x-coordinate.
Returns:
Region.Range. Range of the left most and right most x-coordinate.
"""
return Region.Range(self._x, self._right)

def yrange(self):
""" Defines the Range between the top most and bottom most y-coordinate.
Returns:
Region.Range. Range of the top most and bottom most y-coordinate.
"""
return Region.Range(self._y, self._bottom)

def contains(self, point):
""" Returns True if the provided point is present inside the Region.
Args:
point (Position) A 2d Point position.
Returns:
bool. True if the point is in the Region else False.
"""
return point.x in self.xrange() and point.y in self.yrange()

def points(self):
""" A Region can be represented by basic 2 points defining its top-left and bottom right position.
Returns:
list<Position>. Array of Positions for the Region.
"""
return [Position(self._x, self._y), Position(self._right, self._bottom)]

def containsRegion(self, region):
""" Returns True if the provided region belongs to the current Region.
Args:
region (Region): The region to check for.
Returns:
bool. True if the provided region belongs to the current Region.
"""
# Check if both top-left and bottom-right points of the region fall in the current region
for point in region.points():
# If any of the point is outside of the -> The region can be safely marked as not in current region
if point not in self:
return False

# Else it belongs
return True


class Edge(BaseObject):

def __init__(self, src, dst, parent=None):
Expand Down Expand Up @@ -165,6 +289,9 @@ class Graph(BaseObject):
"""
_cacheDir = ""

# Graph's Region Of Interest
ROI = Region

class IO(object):
""" Centralize Graph file keys and IO version. """
__version__ = "2.0"
Expand Down Expand Up @@ -679,6 +806,26 @@ def nodeOutEdges(self, node):
""" Return the list of edges starting from this node """
return [edge for edge in self.edges if edge.src.node == node]

def nodesInRegion(self, region):
""" Returns the Nodes present in this region.
Args:
region (Graph.ROI): Region to look for nodes.
Returns:
list<Node>. Array of Nodes present in the Region.
"""
# A node with 40 pixels inside the backdrop in terms of height could be considered a candidate ?
nodes = []
for node in self._nodes.values():
# Node's Region
noder = Graph.ROI(node.x, node.y, node.x + node.nodeWidth, node.y + 40)
# If the provided region contains the node region -> add the node to the array of nodes
if region.containsRegion(noder):
nodes.append(node)

return nodes

@changeTopology
def removeNode(self, nodeName):
"""
Expand Down
Loading

0 comments on commit f660d83

Please sign in to comment.