@@ -58,12 +58,13 @@ def _update_edges(self):
5858 trailing edge, hence both the leading and the trailing edges are always
5959 unique.
6060 """
61- if self .xup_coordinates [0 ] != self .xdown_coordinates [0 ]:
62- raise ValueError ('Airfoils must have xup_coordinates[0] \
63- == xdown_coordinates[0]' )
64- if self .xup_coordinates [- 1 ] != self .xdown_coordinates [- 1 ]:
65- raise ValueError ('Airfoils must have xup_coordinates[-1] \
66- == xdown_coordinates[-1]' )
61+ if np .fabs (self .xup_coordinates [0 ] - self .xdown_coordinates [0 ]) > 1e-4 :
62+ raise ValueError ('Airfoils must have xup_coordinates[0] ' \
63+ 'almost equal to xdown_coordinates[0]' )
64+ if np .fabs (
65+ self .xup_coordinates [- 1 ] - self .xdown_coordinates [- 1 ]) > 1e-4 :
66+ raise ValueError ('Airfoils must have xup_coordinates[-1] ' \
67+ 'almost equal to xdown_coordinates[-1]' )
6768
6869 self .leading_edge [0 ] = self .xup_coordinates [0 ]
6970 self .leading_edge [1 ] = self .yup_coordinates [0 ]
@@ -153,7 +154,7 @@ def compute_chord_line(self, n_interpolated_points=None):
153154 aratio = ((self .trailing_edge [1 ] - self .leading_edge [1 ]) /
154155 (self .trailing_edge [0 ] - self .leading_edge [0 ]))
155156 if not (self .xup_coordinates == self .xdown_coordinates
156- ).all () and n_interpolated_points is None :
157+ ).all () and n_interpolated_points is None :
157158 # If x_up != x_down element-wise, then the corresponding y_up and
158159 # y_down can not be comparable, hence a uniform interpolation is
159160 # required. Also in case the interpolated_points is None,
@@ -196,7 +197,7 @@ def compute_camber_line(self, n_interpolated_points=None):
196197 inaccurate measurements for obtaining the camber line.
197198 """
198199 if not (self .xup_coordinates == self .xdown_coordinates
199- ).all () and n_interpolated_points is None :
200+ ).all () and n_interpolated_points is None :
200201 # If x_up != x_down element-wise, then the corresponding y_up and
201202 # y_down can not be comparable, hence a uniform interpolation is
202203 # required. Also in case the interpolated_points is None,
@@ -222,8 +223,8 @@ def deform_camber_line(self, percent_change, n_interpolated_points=None):
222223 The percentage of change is defined as follows:
223224
224225 .. math::
225- \\ frac{new magnitude of max camber - old magnitude of maximum \
226- camber}{ old magnitude of maximum camber} * 100
226+ \\ frac{\\ text{ new magnitude of max camber - old magnitude of maximum \
227+ camber}}{ \\ text{ old magnitude of maximum camber} } * 100
227228
228229 A positive percentage means the new camber is larger than the max
229230 camber value, while a negative percentage indicates the new value
@@ -253,7 +254,7 @@ def deform_camber_line(self, percent_change, n_interpolated_points=None):
253254 self .camber_line [1 ] *= scaling_factor
254255
255256 if not (self .xup_coordinates == self .xdown_coordinates
256- ).all () and n_interpolated_points is None :
257+ ).all () and n_interpolated_points is None :
257258 # If x_up != x_down element-wise, then the corresponding y_up and
258259 # y_down can not be comparable, hence a uniform interpolation is
259260 # required. Also in case the interpolated_points is None,
@@ -265,7 +266,7 @@ def deform_camber_line(self, percent_change, n_interpolated_points=None):
265266 if n_interpolated_points :
266267 (self .xup_coordinates , self .xdown_coordinates , self .yup_coordinates ,
267268 self .ydown_coordinates
268- ) = self .interpolate_coordinates (num = n_interpolated_points )
269+ ) = self .interpolate_coordinates (num = n_interpolated_points )
269270
270271 half_thickness = 0.5 * np .fabs (
271272 self .yup_coordinates - self .ydown_coordinates )
@@ -276,7 +277,7 @@ def deform_camber_line(self, percent_change, n_interpolated_points=None):
276277 @property
277278 def reference_point (self ):
278279 """
279- Return the coordinates of the airfoil 's geometric center .
280+ Return the coordinates of the chord 's mid point .
280281
281282 :return: reference point in 2D
282283 :rtype: numpy.ndarray
@@ -338,7 +339,7 @@ def max_thickness(self, n_interpolated_points=None):
338339 :rtype: float
339340 """
340341 if not (self .xup_coordinates == self .xdown_coordinates
341- ).all () and n_interpolated_points is None :
342+ ).all () and n_interpolated_points is None :
342343 # If x_up != x_down element-wise, then the corresponding y_up and
343344 # y_down can not be comparable, hence a uniform interpolation is
344345 # required. Also in case the interpolated_points is None,
@@ -408,15 +409,23 @@ def rotate(self, rad_angle=None, deg_angle=None):
408409
409410 .. math::
410411 \\ left(\\ begin{matrix} cos (\\ theta) & - sin (\\ theta) \\
412+
411413 sin (\\ theta) & cos (\\ theta) \\ end{matrix}\\ right)
412414
413- Given the coordinates of point
414- :math:`(P) = \\ left(\\ begin{matrix} x \\ y \\ end{matrix}\\ right)`,
415- the rotated coordinates will be:
415+ Given the coordinates of point :math:`P` such that
416416
417417 .. math::
418- P^{'} = \\ left(\\ begin{matrix} x^{'} \\ y^{'} \\ end{matrix}\\ right)
419- = R (\\ theta) \\ cdot P`
418+ (P) = \\ left(\\ begin{matrix} x \\
419+
420+ y \\ end{matrix}\\ right),
421+
422+ Then, the rotated coordinates will be:
423+
424+ .. math::
425+ P^{'} = \\ left(\\ begin{matrix} x^{'} \\
426+
427+ y^{'} \\ end{matrix}\\ right)
428+ = R (\\ theta) \\ cdot P
420429
421430 If a standard right-handed Cartesian coordinate system is used, with
422431 the X-axis to the right and the Y-axis up, the rotation
@@ -431,8 +440,8 @@ def rotate(self, rad_angle=None, deg_angle=None):
431440 """
432441 if rad_angle is not None and deg_angle is not None :
433442 raise ValueError (
434- 'You have to pass either the angle in radians or in degrees, \
435- not both.' )
443+ 'You have to pass either the angle in radians or in degrees,' \
444+ ' not both.' )
436445 if rad_angle :
437446 cosine = np .cos (rad_angle )
438447 sine = np .sin (rad_angle )
@@ -475,9 +484,13 @@ def translate(self, translation):
475484 self .yup_coordinates += translation [1 ]
476485 self .ydown_coordinates += translation [1 ]
477486
478- def flip (self ):
487+ def reflect (self ):
479488 """
480- Flip the airfoil coordinates about both the X-axis and the Y-axis.
489+ Reflect the airfoil coordinates about the origin, i.e. a mirror
490+ transformation is performed about both the X-axis and the Y-axis.
491+
492+ We note that if the foil is cenetered by its reference point at the
493+ origin, then the reflection is just a simple flip.
481494 """
482495 self .xup_coordinates *= - 1
483496 self .xdown_coordinates *= - 1
@@ -504,21 +517,59 @@ def scale(self, factor):
504517 self .ydown_coordinates *= factor
505518 self .translate (ref_point )
506519
507- def plot (self , outfile = None ):
520+ def plot (self ,
521+ profile = True ,
522+ chord_line = False ,
523+ camber_line = False ,
524+ ref_point = False ,
525+ outfile = None ):
508526 """
509527 Plot the airfoil coordinates.
510528
511- :param string outfile: outfile name. If a string is provided then the
529+ :param bool profile: if True, then plot the profile coordinates.
530+ Default value is True
531+ :param bool chord_line: if True, then plot the chord line. Default
532+ value is False
533+ :param bool camber_line: if True, then plot the camber line. Default
534+ value is False
535+ :param bool ref_point: if True, then scatter plot the reference point.
536+ Default value is False
537+ :param str outfile: outfile name. If a string is provided then the
512538 plot is saved with that name, otherwise the plot is not saved.
513539 Default value is None
514540 """
515541 plt .figure ()
516- plt .plot (self .xup_coordinates , self .yup_coordinates )
517- plt .plot (self .xdown_coordinates , self .ydown_coordinates )
542+
543+ if (self .xup_coordinates is None or self .yup_coordinates is None
544+ or self .xdown_coordinates is None
545+ or self .ydown_coordinates is None ):
546+ raise ValueError ('One or all the coordinates have None value.' )
547+
548+ if profile :
549+ plt .plot (self .xup_coordinates , self .yup_coordinates )
550+ plt .plot (self .xdown_coordinates , self .ydown_coordinates )
551+
552+ if chord_line :
553+ if self .chord_line is None :
554+ raise ValueError (
555+ 'Chord line is None. You must compute it first' )
556+ plt .plot (self .chord_line [0 ], self .chord_line [1 ])
557+
558+ if camber_line :
559+ if self .camber_line is None :
560+ raise ValueError (
561+ 'Camber line is None. You must compute it first' )
562+ plt .plot (self .camber_line [0 ], self .camber_line [1 ])
563+
564+ if ref_point :
565+ plt .scatter (self .reference_point [0 ], self .reference_point [1 ])
566+
518567 plt .grid (linestyle = 'dotted' )
519568 plt .axis ('equal' )
520569
521570 if outfile :
522571 if not isinstance (outfile , str ):
523572 raise ValueError ('Output file name must be string.' )
524573 plt .savefig (outfile )
574+ else :
575+ plt .show ()
0 commit comments