Drainage direction on surface with holes

Hi all,
I have been working with this script linked (Rhino V6 version below) to see drainage over a surface, but my issue is it was never designed the trimmed surfaces in mind so I have been trying to add this.

I know I needed to add another elif statement in to stop the loop from running when the point is beyond the trimmed surface but I have not been able to make it work whatever I try.

My esif is called onSurface() and I have also tried to make the trimmed surface a brep.face as that’s what the points in trim wants in the def_init at the top of the code but not getting an output where the drainage crvs do not keep going over the trimmed surface.

I have attached the code in a python component below also with a simple surface example.
Drainage Problem.gh (36.8 KB)

import Rhino
import ghpythonlib.components as ghc

class DrainBoid(object):
    def __init__(self, point3d, surface, stepsize=0.5, maxsteps=None, tolerance=0.001):
        self.start = point3d
        self.pos = self.start
        result, self.u, self.v = surface.ClosestPoint(self.pos)
        self.surface = surface
        self.stepsize = stepsize
        self.points = [self.start]
        self.state = 'on'
        self.tolerance = tolerance
        self.maxsteps = maxsteps
        brep = surface.ToBrep()
        breptrimmed = brep.CopyTrimCurves(brep.Faces[0],surface,0.001)
        self.brepFace = breptrimmed.Faces[0]
        

    def makeDrainCurve(self):
        i = 0
        while self.state == 'on':
            i += 1
            if self.maxsteps:
                if i >= self.maxsteps:
                    self.state = 'finished'
            self.nextStep()
        return Rhino.Geometry.Curve.CreateControlPointCurve(self.points, 1)

    def nextStep(self):
        result, newFrame = self.surface.FrameAt(self.u, self.v)
        # create a vector from newFrame XAxis
        downVect = newFrame.XAxis
        # figure out hw far to rotate it.
        deltaAngle = Rhino.Geometry.Vector3d.VectorAngle( downVect, Rhino.Geometry.Vector3d(0.0, 0.0, -1.0), newFrame )
        # rotate it in the plane
        downVect.Rotate( deltaAngle, newFrame.ZAxis)
        # set the length
        downVect = downVect.Multiply( self.stepsize, downVect )
        spacePoint = Rhino.Geometry.Point3d.Add(self.pos, downVect)
        result, self.u, self.v = self.surface.ClosestPoint(spacePoint)
        out, newPoint, vects = self.surface.Evaluate(self.u, self.v, 0)
        if newPoint.Z >= self.pos.Z: # if higher
            self.state = 'finished'
        elif not self.checkTolerance(newPoint): # if too close
            self.state = 'finished'
        elif not self.onSurface():
            self.state = 'finished'
        else:
            self.updatePos(newPoint)

    def updatePos(self, newPoint):
        self.points.append(newPoint)
        self.pos = newPoint

    def checkTolerance(self, other):
        # checks against another point
        # if it is outside of tolerance, returns True
        return self.pos.DistanceTo( other ) > self.tolerance

    def onSurface(self):
        # checks if point is on trimmed surface
        # if it is outside returns True
        return self.brepFace.IsPointOnFace(self.u,self.v) == Rhino.Geometry.PointFaceRelation.Interior

if terrainSurface:
    b = DrainBoid(startPoint, terrainSurface, stepSize, maxSteps, tol)
    crv= b.makeDrainCurve()

@dale This is the code linked to the previous question regarding converting surfaces to breps.

@piac Have you has this issue that surface becomes untrimmed in the python component as you can see here the water flow crvs are still following the surface even though its trimmed.

For anyone interested I have solved this issue using this code to with the input changed to Brep to bring in the trimmed surface to Python then access the untrimmed surface for the surface commands such as evaluate surfac.

    self.brepFace = surface.Faces[0]
    self.surface = self.brepFace.DuplicateSurface()

The updated code here. Drainage Problem.gh (43.9 KB)

1 Like