You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A relatively easy way to subdivide long lines based on distance to wells or other element vertices is by:
Projecting all (well) vertices onto a line segment and computing the (perpendicular) distance
Find where the projected point falls. Divide the segment in half if its length is larger than the distance to the vertex.
Repeat until all projections fall in a segment that is smaller than the distance to the vertex.
For example:
V1 and V2 are the vertices of the line segment.
P1 and P2 are the vertices to two wells
The orange and green lines indicate the projection
All other markers denote the created subdivision vertices
This has some nice properties: we don't have to introduce any logic when projections are close to each other, or when a vertex is far away:
def_halve_segments(vertices, segments, index):
"""Halve segments at indices provided by `index`."""halved=segments[index] *0.5returnnp.insert(vertices, index, vertices[index] -halved)
defbisect(vertices, projections, distances):
""" Iteratively half a line segment, defined by vertices, until the line segments are smaller than the provided distances. The result is such that every projected point falls within a segment that is shorter than the distance to the point. Parameters ---------- vertices: np.array of floats Location of the vertices, expressed as length along the line. projections: np.array of floats Location of the projected points, expressed as length along the line. distances: np.array of floats Distance of the points to the line. Returns ------- refined_vertices: np.array of floats Location of new vertices along line. """deffind_split(vertices, projections, distances):
index=np.searchsorted(vertices, projections)
segments=np.diff(vertices, prepend=0.0)
to_split=segments[index] >distancesreturnnp.unique(index[to_split]), segments, to_split.any()
index, segments, to_split=find_split(vertices, projections, distances)
whileto_split:
vertices=_halve_segments(vertices, segments, index)
index, segments, to_split=find_split(vertices, projections, distances)
returnvertices
However, just like in mesh generation with quadtrees or octrees, the line segments are not always "balanced" (a 2:1 ratio at max between neigbhors), see the first segment with the second:
Fortunately, this is not difficult to implement in 1D. I'm not sure if it's worthwhile...
defbalance(vertices):
""" Iteratively half line segments until each segment is at most twice as big as a neighboring segment. Parameters ---------- vertices: np.array of floats Location of the vertices, expressed as length along the line. Returns ------- refined_vertices: np.array of floats Location of new vertices along line. """deffind_split(vertices):
segments=np.diff(vertices)
left=segments[:-1]
right=segments[1:]
to_split=np.zeros(segments, dtype=bool)
# 0.49 should be sufficient to avoid floating point roundoffto_split[:-1] = (0.49*left) >rightto_split[1:] = (0.49*right) >leftindex=np.argwhere(to_split) +1# TODO: checkreturnindex, segments, to_split.any()
index, segments, to_split=find_split(vertices)
whileto_split:
vertices=_halve_segments(vertices, segments, index)
index, segments, to_split=find_split(vertices)
returnvertices
Some other thoughts:
I think it makes sense to define a "refine" method on the model object, because it should only be done after all elements are added to the model. Then:
A collection of all vertices can be made.
Project these on every line segment and compute distance.
Split every segment with the logic above.
Replace the element in the model by one with the additional vertices inserted (?)
It's also possible to refine and "balance" a linestring in its entirety by expressing the vertices as distance measured along the linestring.
Maybe (only) somewhat useful when two segments have very obtuse angles with each other?
There might be an indexing trick to get this to work when the geometry forms a ring (e.g. numpy take has a "wrap" mode).
The text was updated successfully, but these errors were encountered:
A relatively easy way to subdivide long lines based on distance to wells or other element vertices is by:
For example:
This has some nice properties: we don't have to introduce any logic when projections are close to each other, or when a vertex is far away:
However, just like in mesh generation with quadtrees or octrees, the line segments are not always "balanced" (a 2:1 ratio at max between neigbhors), see the first segment with the second:
Fortunately, this is not difficult to implement in 1D. I'm not sure if it's worthwhile...
Some other thoughts:
I think it makes sense to define a "refine" method on the model object, because it should only be done after all elements are added to the model. Then:
A collection of all vertices can be made.
Project these on every line segment and compute distance.
Split every segment with the logic above.
Replace the element in the model by one with the additional vertices inserted (?)
It's also possible to refine and "balance" a linestring in its entirety by expressing the vertices as distance measured along the linestring.
Maybe (only) somewhat useful when two segments have very obtuse angles with each other?
There might be an indexing trick to get this to work when the geometry forms a ring (e.g. numpy take has a "wrap" mode).
The text was updated successfully, but these errors were encountered: