"""
The Grid submodule contains all classes that are related to **Revit** grids. It helps you
to quickly get filtered lists of grid lines or find closests intersections to given points in
orthogonal grids.
"""
[docs]class Grid(object):
"""
The ``Grid`` class is the base class for other grid classes such as the :class:`OrthoGrid` class.
A grid object contains a collection of grid lines. That collection can be filtered when creating a grid instance.
The following example will create a grid object based on all grid lines with a type name
that either contains "main" or "sub"::
grid = revitron.Grid('main, sub')
Alternatively you can create a :class:`OrthoGrid` object only including orthogonal grid lines::
ortho = revitron.OrthoGrid('main, sub')
"""
[docs] def __init__(self, typeFilterCsv=False):
"""
Creates a new ``Grid`` instance. A comma separated string can be passed as an argument to filter
the grid elements by their type name.
Args:
typeFilterCsv (string, optional): A CSV filter. Defaults to False.
"""
self._lines = self._getLines(typeFilterCsv)
@property
def lines(self):
"""
The dict of grid lines contained in the ``Grid`` object where the grid line name serves as key.
Returns:
dict: A dict of Revit grid line elements where the grid name serves as key
"""
return self._lines
def _getLines(self, typeFilterCsv=False):
"""
Create the filtered dict of grid lines.
Args:
typeFilterCsv (string, optional): A CSV filter. Defaults to False.
Returns:
dict: A dict of Revit grid line elements where the grid name serves as key
"""
if hasattr(self, '_lines'):
return self._lines
import revitron
fltr = revitron.Filter().byCategory('Grids').noTypes()
if typeFilterCsv:
fltr = fltr.byStringContainsOneInCsv('Type', typeFilterCsv)
lines = dict()
for line in fltr.getElements():
try:
lines[line.Name] = line
except:
pass
return lines
[docs]class OrthoGrid(Grid):
"""
In contrast to the ``Grid`` class, the ``OrthoGrid`` object only contains grid lines that are orthogonal.
The following example will create a orthogonal grid object based on all grid lines with a type name
that either contains "main" or "sub"::
grid = revitron.OrthoGrid('main, sub')
"""
[docs] @staticmethod
def newLineX(X, name):
"""
Create a new grid line that is defined by single **X** value and therefore is parallel to the **Y** axis.
.. note:: Note that the grid line created by this methods marks a position on the **X** axis that
is represented by a line that is parallel to the **Y** axis.
Args:
X (float): The position on the X axis
name (string): The name of the new grid line
Returns:
object: A Revit grid element
"""
import revitron
xyz = revitron.DB.XYZ
start = xyz(X, 50, 0)
end = xyz(X, -50, 0)
return revitron.Create.GridLineLinear(start, end, name)
[docs] @staticmethod
def newLineY(Y, name):
"""
Create a new grid line that is defined by single **Y** value and therefore is parallel to the **X** axis.
.. note:: Note that the grid line created by this methods marks a position on the **Y** axis that
is represented by a line that is parallel to the **X** axis.
Args:
Y (float): The position on the Y axis
name (string): The name of the new grid line
Returns:
object: A Revit grid element
"""
import revitron
xyz = revitron.DB.XYZ
start = xyz(-50, Y, 0)
end = xyz(50, Y, 0)
return revitron.Create.GridLineLinear(start, end, name)
@property
def lines(self):
"""
An object that contains one ``X`` and one ``Y`` property, both dicts containing
grid line elements where the grid name serves as key.
The ``X`` property contains all grid lines that are defined by a single value on the X axis
and the the ``Y`` property contains all grid lines that are defined by a single value on the Y axis.
.. note:: Note that the lines of the **X** property are by definition always parallel to the **Y** axis
since they are defined by a single **X** value and vice versa.
Returns:
object: An object containing orthogonal grid elements split into X and Y lines
"""
return self._lines
def _getLines(self, typeFilterCsv=False):
"""
Create an object that contains one ``X`` and one ``Y`` property, both dicts containing
grid line elements where the grid name serves as key.
The ``X`` property contains all grid lines that are defined by a single value on the X axis
and the the ``Y`` property contains all grid lines that are defined by a single value on the Y axis.
Args:
typeFilterCsv (string, optional): A CSV filter. Defaults to False.
Returns:
object: An object containing orthogonal grid elements split into X and Y lines
"""
if hasattr(self, '_lines'):
return self._lines
import revitron
x = dict()
y = dict()
lines = super(OrthoGrid, self)._getLines(typeFilterCsv).values()
for line in lines:
try:
p0 = line.Curve.GetEndPoint(0)
p1 = line.Curve.GetEndPoint(1)
if round(p0.X, 3) == round(p1.X, 3):
x[line.Name] = line
if round(p0.Y, 3) == round(p1.Y, 3):
y[line.Name] = line
except:
pass
return revitron.AttrDict({'X': x, 'Y': y})
def _getLinesByPosition(self):
"""
Create an object that contains one ``X`` and one ``Y`` property, both dicts containing
grid line elements that are defined by a single value on an axis where that value serves as dict key.
The ``X`` property contains all grid lines that are defined by a single value on the X axis
and the the ``Y`` property contains all grid lines that are defined by a single value on the Y axis.
Returns:
object: An object containing orthogonal grid elements split into X and Y direction
"""
if not hasattr(self, '_linesByPosition'):
import revitron
x = dict()
y = dict()
for line in self._lines.X.values():
p0 = line.Curve.GetEndPoint(0)
x[round(p0.X, 3)] = line
for line in self._lines.Y.values():
p0 = line.Curve.GetEndPoint(0)
y[round(p0.Y, 3)] = line
self._linesByPosition = revitron.AttrDict({'X': x, 'Y': y})
return self._linesByPosition
[docs] def closestIntersectionToPointTopLeft(self, point):
"""
Find the grid intersection that is closest to a given point on the top left side.
Args:
point (object): A Revit ``XYZ`` object
Returns:
object: A :class:`OrthoGridIntersection` object
"""
top = None
left = None
lines = self._getLinesByPosition()
xLinePos = sorted(lines.X.keys())
yLinePos = sorted(lines.Y.keys(), reverse=True)
for x in xLinePos:
if x > point.X:
break
left = x
for y in yLinePos:
if y < point.Y:
break
top = y
if top and left:
return OrthoGridIntersection(lines.X[left], lines.Y[top])
[docs] def closestIntersectionToPointBottomRight(self, point):
"""
Find the grid intersection that is closest to a given point on the bottom right side.
Args:
point (object): A Revit ``XYZ`` object
Returns:
object: A :class:`OrthoGridIntersection` object
"""
bottom = None
right = None
lines = self._getLinesByPosition()
xLinePos = sorted(lines.X.keys())
yLinePos = sorted(lines.Y.keys(), reverse=True)
for x in xLinePos:
right = x
if x > point.X:
break
for y in yLinePos:
bottom = y
if y < point.Y:
break
if bottom and right:
return OrthoGridIntersection(lines.X[right], lines.Y[bottom])
[docs]class OrthoGridIntersection:
"""
An ``OrthoGridIntersection`` object contains all relevant information about an intersection
of two orthogonal grid lines.
"""
[docs] def __init__(self, lineX, lineY):
"""
Create a new intersection object based on two orthogonal grid lines.
Args:
gridX (object): A Revit grid element
gridY (object): A Revit grid element
"""
self._lineX = lineX
self._lineY = lineY
self._nameX = ''
self._nameY = ''
self._X = None
self._Y = None
if lineX:
self._X = lineX.Curve.GetEndPoint(0).X
self._nameX = lineX.Name
if lineY:
self._Y = lineY.Curve.GetEndPoint(0).Y
self._nameY = lineY.Name
@property
def lineX(self):
"""
The Revit grid line element that is defined by a single value on the **X** axis
and is parallel to the **Y** axis.
Returns:
object: A Revit grid element
"""
return self._lineX
@property
def lineY(self):
"""
The Revit grid line element that is defined by a single value on the **Y** axis
and is parallel to the **X** axis.
Returns:
object: A Revit grid element
"""
return self._lineY
@property
def nameX(self):
"""
The name of the grid line element that is defined by a single value on the **X** axis.
Returns:
string: The name of the grid
"""
return self._nameX
@property
def nameY(self):
"""
The name of the grid line element that is defined by a single value on the **Y** axis.
Returns:
string: The name of the grid
"""
return self._nameY
@property
def X(self):
"""
The **X** coordinate of the intersection on plan.
Returns:
float: The X coordinate
"""
return self._X
@property
def Y(self):
"""
The **Y** coordinate of the intersection on plan.
Returns:
float: The Y coordinate
"""
return self._Y