Commit 479751a8 authored by Dennis Gläser's avatar Dennis Gläser
Browse files

[python][sampling] add cylinder point sampler allowing for custom distros

parent 8a99f1ac
......@@ -5,7 +5,14 @@ class BoxPointSampler:
"""Class to sample random points within a box."""
def __init__(self, samplerX, samplerY, samplerZ):
"""Create the sampler from random variable samplers for the coordinate directions."""
"""
Create the sampler from random variable samplers for the coordinate directions.
Parameters:
samplerX: sampler that samples from a distribution for the x-coordinate
samplerY: sampler that samples from a distribution for the y-coordinate
samplerZ: sampler that samples from a distribution for the z-coordinate
"""
self.samplerX = samplerX
self.samplerY = samplerY
self.samplerZ = samplerZ
......@@ -18,6 +25,53 @@ class BoxPointSampler:
from frackit.geometry import Point_3
return Point_3(x, y, z)
class CylinderPointSampler:
"""Class to sample random points within a cylinder."""
def __init__(self, cylinder, samplerR2, samplerPhi, samplerZ):
"""
Create the sampler from random variable samplers for the coordinate directions.
Points on the cylinder are represented in cylinder coordinates, i.e. by a radial,
an angular and a height coordinate. Points on the cylinder are sampled based on
the given distributions for the squared radius, the angle and the height.
Parameters:
cylinder: an instance of a cylinder class
samplerR2: sampler that samples from a distribution for the squared radius
samplerPhi: sampler that samples from a distribution for the angular coordinate
samplerZ: sampler that samples from a distribution for the height
"""
self.cylinder = cylinder
self.samplerR2 = samplerR2
self.samplerPhi = samplerPhi
self.samplerZ = samplerZ
def sample(self):
from frackit.geometry import Vector_3
a = Vector_3(self.cylinder.bottomFace().majorAxis());
b = Vector_3(self.cylinder.bottomFace().minorAxis());
n = Vector_3(self.cylinder.bottomFace().normal());
from math import sqrt, sin, cos
r = sqrt(self.samplerR2())
phi = self.samplerPhi()
z = self.samplerZ()
a *= r*cos(phi);
b *= r*sin(phi);
n *= z;
result = self.cylinder.bottomFace().center();
result += a;
result += b;
result += n;
return result;
# creator for a uniform sampler within an interval
def uniformIntervalSamplerCreator():
def makeSampler(min, max):
......@@ -27,16 +81,58 @@ def uniformIntervalSamplerCreator():
return doSample
return makeSampler
def makeBoxPointSampler(box,
samplerCreatorX=uniformIntervalSamplerCreator(),
samplerCreatorY=uniformIntervalSamplerCreator(),
samplerCreatorZ=uniformIntervalSamplerCreator()):
"""Creates a BoxPointSampler using the provided creators for samplers on intervals.
The creators default to uniform interval sampler creators if nothing is specified."""
# make samplers
samplerX = samplerCreatorX(box.xMin(), box.xMax())
samplerY = samplerCreatorY(box.yMin(), box.yMax())
samplerZ = samplerCreatorZ(box.zMin(), box.zMax())
def makePointSampler(geometry,
samplerCreatorBase1=uniformIntervalSamplerCreator(),
samplerCreatorBase2=uniformIntervalSamplerCreator(),
samplerCreatorBase3=uniformIntervalSamplerCreator()):
"""
Creates a point sampler for the provided three-dimensional geometry using the
provided creators for samplers on intervals.
Points on the three-dimensional geometries considered here can be expressed in
terms of tuples of coordinates (a1, a2, a3), where the entries of the tuple refer
to the coordinate values with respect to the geometry-local basis. Moreover,
the considered geometries are finite, which is expressed in terms of lower and
upper bounds for the coordinates. For instance, the points within an axis-aligned
box fall into the intervals ([xMin, xMax], [yMin, yMax], [zMin, zMax]). For a
cylinder, described in cylinder coordinates, all points fall into the intervals
([0, r], [0, 2*Pi], [0, H]), where r is the radius an H is the height of the
cylinder. The provided sampler creators are used to build samplers that sample
coordinates within these intervals following a user-defined distribution. For
more details on the meaning of the samplers, have a look at the geometry-specific
point sampler implementations.
The creators default to uniform interval sampler creators if nothing is specified.
Parameters:
geometry: the geometry for which a point sampler is to be created
samplerCreatorBase1: creator for a sampler of coordinate values for the first coordinate
samplerCreatorBase2: creator for a sampler of coordinates values for the second coordinate
samplerCreatorBase3: creator for a sampler of coordinates values for the third coordinate
"""
# box point sampler
if geometry.name() == "Box":
samplerX = samplerCreatorBase1(geometry.xMin(), geometry.xMax())
samplerY = samplerCreatorBase2(geometry.yMin(), geometry.yMax())
samplerZ = samplerCreatorBase3(geometry.zMin(), geometry.zMax())
return BoxPointSampler(samplerX, samplerY, samplerZ)
# cylinder point sampler
if geometry.name() == "Cylinder":
import math
samplerR2 = samplerCreatorBase1(0.0, geometry.radius())
samplerPhi = samplerCreatorBase2(0.0, 2.0*math.pi)
samplerZ = samplerCreatorBase3(0.0, geometry.height())
return CylinderPointSampler(geometry, samplerR2, samplerPhi, samplerZ)
# hollow cylinder point sampler
if geometry.name() == "HollowCylinder":
import math
samplerR2 = samplerCreatorBase1(geometry.innerRadius(), geometry.outerRadius())
samplerPhi = samplerCreatorBase2(0.0, 2.0*math.pi)
samplerZ = samplerCreatorBase3(0.0, geometry.height())
return CylinderPointSampler(geometry.fullCylinder(), samplerR2, samplerPhi, samplerZ)
return BoxPointSampler(samplerX, samplerY, samplerZ)
raise NotImplementedError("No point sample creation formula implemented for provided geometry: " + geometry.name())
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment