Skip to content

Commit f660d83

Browse files
Vivek VERMAVivek VERMA
authored andcommitted
Added Backdrop Node for Meshroom graph
Nodes now have a size defined Added the notion of Region in a graph
1 parent 88f9d4b commit f660d83

File tree

8 files changed

+558
-21
lines changed

8 files changed

+558
-21
lines changed

meshroom/core/desc.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,22 @@ class Node(object):
702702
value="",
703703
invalidate=False,
704704
),
705+
FloatParam(
706+
name="nodeWidth",
707+
label="Node Width",
708+
description="The Node's Width.",
709+
value=160,
710+
range=None,
711+
enabled=False # Hidden always
712+
),
713+
FloatParam(
714+
name="nodeHeight",
715+
label="Node Height",
716+
description="The Node's Height.",
717+
value=120,
718+
range=None,
719+
enabled=False # Hidden always
720+
),
705721
ColorParam(
706722
name="color",
707723
label="Color",
@@ -779,6 +795,68 @@ def __init__(self):
779795
def processChunk(self, chunk):
780796
pass
781797

798+
def stopProcess(self, chunk):
799+
pass
800+
801+
802+
class Backdrop(InputNode):
803+
""" A Backdrop for other nodes.
804+
"""
805+
806+
# The internal inputs' of Backdrop Node needs a Integer Field to determine the font size for the comment
807+
internalInputs = [
808+
StringParam(
809+
name="invalidation",
810+
label="Invalidation Message",
811+
description="A message that will invalidate the node's output folder.\n"
812+
"This is useful for development, we can invalidate the output of the node when we modify the code.\n"
813+
"It is displayed in bold font in the invalidation/comment messages tooltip.",
814+
value="",
815+
semantic="multiline",
816+
advanced=True,
817+
uidIgnoreValue="", # If the invalidation string is empty, it does not participate to the node's UID
818+
),
819+
StringParam(
820+
name="comment",
821+
label="Comments",
822+
description="User comments describing this specific node instance.\n"
823+
"It is displayed in regular font in the invalidation/comment messages tooltip.",
824+
value="",
825+
semantic="multiline",
826+
invalidate=False,
827+
),
828+
IntParam(
829+
name="fontSize",
830+
label="Font Size",
831+
description="The Font size for the User Comment on the Backdrop.",
832+
value=12,
833+
range=(6, 100, 1),
834+
),
835+
FloatParam(
836+
name="nodeWidth",
837+
label="Node Width",
838+
description="The Backdrop Node's Width.",
839+
value=600,
840+
range=None,
841+
enabled=False # Hidden always
842+
),
843+
FloatParam(
844+
name="nodeHeight",
845+
label="Node Height",
846+
description="The Backdrop Node's Height.",
847+
value=400,
848+
range=None,
849+
enabled=False # Hidden always
850+
),
851+
ColorParam(
852+
name="color",
853+
label="Color",
854+
description="Custom color for the node (SVG name or hexadecimal code).",
855+
value="",
856+
invalidate=False,
857+
)
858+
]
859+
782860

783861
class CommandLineNode(Node):
784862
"""

meshroom/core/graph.py

Lines changed: 148 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from meshroom.core import Version
1717
from meshroom.core.attribute import Attribute, ListAttribute, GroupAttribute
1818
from meshroom.core.exception import StopGraphVisit, StopBranchVisit
19-
from meshroom.core.node import nodeFactory, Status, Node, CompatibilityNode
19+
from meshroom.core.node import nodeFactory, Status, Node, CompatibilityNode, Position
2020

2121
# Replace default encoder to support Enums
2222

@@ -56,6 +56,130 @@ def GraphModification(graph):
5656
graph.updateEnabled = enabled
5757

5858

59+
class Region:
60+
""" Defines the boundaries for a Region on the 2d Plane (Graph in our Context).
61+
"""
62+
63+
class Range:
64+
""" Defines a Range between two points in the Graph or 2d Plane, inclusive of the 2nd Point.
65+
"""
66+
67+
def __init__(self, x, y):
68+
""" Constructor.
69+
70+
Args:
71+
x (int | float): An integer or float start.
72+
y (int | float): An integer or float end.
73+
"""
74+
# Internal Coords
75+
self._x = x
76+
self._y = y
77+
78+
def __repr__(self):
79+
""" Represents the instance.
80+
"""
81+
return f"Range::{self._x}, {self._y}"
82+
83+
def __contains__(self, _i):
84+
""" Returns True if the provided integer or float falls between the start and the end point of the range.
85+
"""
86+
return self._x < _i <= self._y
87+
88+
89+
def __init__(self, x=0, y=0, right=0, bottom=0):
90+
""" Constructor.
91+
92+
Args:
93+
x (int | float): The x coordinate of the top-left point on the Region.
94+
y (int | float): The y coordinate of the top-left point on the Region.
95+
right (int | float): The x coordinate of the bottom-right point on the Region.
96+
bottom (int | float): The y coordinate of the bottom-right point on the Region.
97+
"""
98+
# The coords of the Region can be represented as
99+
# (x, y)
100+
# .------------------------.
101+
# | |
102+
# | |
103+
# | |
104+
# | |
105+
# '------------------------'
106+
# (right, bottom)
107+
self._x = x
108+
self._y = y
109+
self._right = right
110+
self._bottom = bottom
111+
112+
# Properties
113+
x = property(lambda self: self._x)
114+
y = property(lambda self: self._y)
115+
right = property(lambda self: self._right)
116+
bottom = property(lambda self: self._bottom)
117+
118+
def __contains__(self, point):
119+
""" Returns True if the provided Point is present in the Region.
120+
"""
121+
return self.contains(point)
122+
123+
def __repr__(self):
124+
""" Represents the instance.
125+
"""
126+
return f"Region::{self.points()}"
127+
128+
# Public
129+
def xrange(self):
130+
""" Defines the Range between the left most and right most x-coordinate.
131+
132+
Returns:
133+
Region.Range. Range of the left most and right most x-coordinate.
134+
"""
135+
return Region.Range(self._x, self._right)
136+
137+
def yrange(self):
138+
""" Defines the Range between the top most and bottom most y-coordinate.
139+
140+
Returns:
141+
Region.Range. Range of the top most and bottom most y-coordinate.
142+
"""
143+
return Region.Range(self._y, self._bottom)
144+
145+
def contains(self, point):
146+
""" Returns True if the provided point is present inside the Region.
147+
148+
Args:
149+
point (Position) A 2d Point position.
150+
151+
Returns:
152+
bool. True if the point is in the Region else False.
153+
"""
154+
return point.x in self.xrange() and point.y in self.yrange()
155+
156+
def points(self):
157+
""" A Region can be represented by basic 2 points defining its top-left and bottom right position.
158+
159+
Returns:
160+
list<Position>. Array of Positions for the Region.
161+
"""
162+
return [Position(self._x, self._y), Position(self._right, self._bottom)]
163+
164+
def containsRegion(self, region):
165+
""" Returns True if the provided region belongs to the current Region.
166+
167+
Args:
168+
region (Region): The region to check for.
169+
170+
Returns:
171+
bool. True if the provided region belongs to the current Region.
172+
"""
173+
# Check if both top-left and bottom-right points of the region fall in the current region
174+
for point in region.points():
175+
# If any of the point is outside of the -> The region can be safely marked as not in current region
176+
if point not in self:
177+
return False
178+
179+
# Else it belongs
180+
return True
181+
182+
59183
class Edge(BaseObject):
60184

61185
def __init__(self, src, dst, parent=None):
@@ -165,6 +289,9 @@ class Graph(BaseObject):
165289
"""
166290
_cacheDir = ""
167291

292+
# Graph's Region Of Interest
293+
ROI = Region
294+
168295
class IO(object):
169296
""" Centralize Graph file keys and IO version. """
170297
__version__ = "2.0"
@@ -679,6 +806,26 @@ def nodeOutEdges(self, node):
679806
""" Return the list of edges starting from this node """
680807
return [edge for edge in self.edges if edge.src.node == node]
681808

809+
def nodesInRegion(self, region):
810+
""" Returns the Nodes present in this region.
811+
812+
Args:
813+
region (Graph.ROI): Region to look for nodes.
814+
815+
Returns:
816+
list<Node>. Array of Nodes present in the Region.
817+
"""
818+
# A node with 40 pixels inside the backdrop in terms of height could be considered a candidate ?
819+
nodes = []
820+
for node in self._nodes.values():
821+
# Node's Region
822+
noder = Graph.ROI(node.x, node.y, node.x + node.nodeWidth, node.y + 40)
823+
# If the provided region contains the node region -> add the node to the array of nodes
824+
if region.containsRegion(noder):
825+
nodes.append(node)
826+
827+
return nodes
828+
682829
@changeTopology
683830
def removeNode(self, nodeName):
684831
"""

0 commit comments

Comments
 (0)