Created shaft wizard (moved here from PartDesign branch)
This commit is contained in:
152
src/Mod/PartDesign/WizardShaft/SegmentFunction.py
Normal file
152
src/Mod/PartDesign/WizardShaft/SegmentFunction.py
Normal file
@@ -0,0 +1,152 @@
|
||||
#/******************************************************************************
|
||||
# * Copyright (c)2012 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This library is free software; you can redistribute it and/or *
|
||||
# * modify it under the terms of the GNU Library General Public *
|
||||
# * License as published by the Free Software Foundation; either *
|
||||
# * version 2 of the License, or (at your option) any later version. *
|
||||
# * *
|
||||
# * This library is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this library; see the file COPYING.LIB. If not, *
|
||||
# * write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
# * Suite 330, Boston, MA 02111-1307, USA *
|
||||
# * *
|
||||
# ******************************************************************************/
|
||||
|
||||
class SegmentFunctionSegment:
|
||||
"One segment of a segment function"
|
||||
start = 0
|
||||
variable = "x"
|
||||
coefficient = 0
|
||||
exponent = 0
|
||||
|
||||
def __init__(self, st, var, coeff, exp):
|
||||
self.start = st
|
||||
self.variable = var
|
||||
self.coefficient = coeff
|
||||
self.exponent = exp
|
||||
|
||||
def hasStart(self, xval):
|
||||
"Return true if the start of this segment is xval"
|
||||
#FIXME: 1E-9 is arbitrary here. But since units are in meters, 1E-9 is a nanometer...
|
||||
return abs(self.start - xval) < 1E-9
|
||||
|
||||
def value(self, xval):
|
||||
if xval < self.start:
|
||||
return 0
|
||||
else:
|
||||
return self.coefficient * pow(xval - self.start, self.exponent)
|
||||
|
||||
def clone(self):
|
||||
return SegmentFunctionSegment(self.start, self.variable, self.coefficient, self.exponent)
|
||||
|
||||
def negate(self):
|
||||
self.coefficient *= -1
|
||||
|
||||
def integrate(self):
|
||||
self.exponent = self.exponent + 1
|
||||
self.coefficient = self.coefficient * 1 / self.exponent
|
||||
|
||||
def asString(self):
|
||||
return "%f * {%s - %f}^%i" % (self.coefficient, self.variable, self.start, self.exponent)
|
||||
|
||||
class SegmentFunction:
|
||||
"Function that is defined segment-wise"
|
||||
variable = "x"
|
||||
segments = []
|
||||
name = "f(x)"
|
||||
|
||||
def __init__(self, name = "f(x)"):
|
||||
self.variable = "x"
|
||||
self.segments = []
|
||||
self.name = name
|
||||
|
||||
def negate(self):
|
||||
for s in self.segments:
|
||||
s.negate()
|
||||
return self
|
||||
|
||||
def index(self, xval):
|
||||
"Find insert position for start value xval"
|
||||
lastStart = 0.0
|
||||
for i in range(len(self.segments)):
|
||||
newStart = self.segments[i].start
|
||||
if (xval >= lastStart) and (xval < newStart):
|
||||
return i
|
||||
lastStart = newStart
|
||||
return len(self.segments)
|
||||
|
||||
def buildFromDict(self, var, dict):
|
||||
self.variable = var
|
||||
for key in sorted(dict.iterkeys()):
|
||||
#if abs(dict[key]) > 1E-9:
|
||||
self.segments.append(SegmentFunctionSegment(key, var, dict[key], 0))
|
||||
|
||||
def addSegments(self, dict):
|
||||
for key in sorted(dict.iterkeys()):
|
||||
if abs(dict[key]) > 1E-9:
|
||||
self.segments.insert(self.index(key), SegmentFunctionSegment(key, self.variable, dict[key], 0))
|
||||
|
||||
def setMaxX(self, mx):
|
||||
self.maxX = mx
|
||||
|
||||
def value(self, xval):
|
||||
"Return the value of the function at the specified x value"
|
||||
result = 0
|
||||
for s in self.segments:
|
||||
result = result + s.value(xval)
|
||||
return result
|
||||
|
||||
def lowervalue(self, xval):
|
||||
"Return the value of the previous segment at the specified x value"
|
||||
result = 0
|
||||
for s in self.segments:
|
||||
result = result + s.value(xval - 1E-8)
|
||||
return result
|
||||
|
||||
def clone(self):
|
||||
result = SegmentFunction()
|
||||
result.variable = self.variable
|
||||
for s in self.segments:
|
||||
result.segments.append(s.clone())
|
||||
return result
|
||||
|
||||
def integrate(self):
|
||||
"Integrate all segments with respect to the variable"
|
||||
for s in self.segments:
|
||||
s.integrate()
|
||||
|
||||
def integrated(self):
|
||||
"Return a copy of self integrated with respect to the variable"
|
||||
result = self.clone()
|
||||
result.integrate()
|
||||
return result
|
||||
|
||||
def evaluate(self, maxX, pointsX):
|
||||
# Note: This usually creates a few more points than specified in pointsX
|
||||
offset = (maxX - self.segments[0].start) / (pointsX - 1)
|
||||
xvals = set([self.segments[0].start + s * offset for s in range(pointsX)])
|
||||
starts = set([self.segments[i].start for i in range(len(self.segments))])
|
||||
xvals = xvals.union(starts) # Make sure we have a point on each segment start
|
||||
result = []
|
||||
for xval in sorted(xvals):
|
||||
if xval in starts:
|
||||
result.append( (xval, self.lowervalue(xval)) ) # create double point at segment border
|
||||
result.append( (xval, self.value(xval)) )
|
||||
return result
|
||||
|
||||
def output(self):
|
||||
print self.name, " = ",
|
||||
for i in range(len(self.segments)):
|
||||
print self.segments[i].asString(),
|
||||
if i < len(self.segments) - 1:
|
||||
print " + ",
|
||||
print ""
|
||||
|
||||
Reference in New Issue
Block a user