text: /**
   * @class Ext.chart.series.sprite.Pie3DPart
   * @extends Ext.draw.sprite.Path
   *
   * Pie3D series sprite.
   */
  Ext.define('Ext.chart.series.sprite.Pie3DPart', {
      extend: 'Ext.draw.sprite.Path',
      mixins: {
          markerHolder: 'Ext.chart.MarkerHolder'
      },
      alias: 'sprite.pie3dPart',
  
      inheritableStatics: {
          def: {
              processors: {
                  /**
                   * @cfg {Number} [centerX=0]
                   * The central point of the series on the x-axis.
                   */
                  centerX: 'number',
  
                  /**
                   * @cfg {Number} [centerY=0]
                   * The central point of the series on the x-axis.
                   */
                  centerY: 'number',
  
                  /**
                   * @cfg {Number} [startAngle=0]
                   * The starting angle of the polar series.
                   */
                  startAngle: 'number',
  
                  /**
                   * @cfg {Number} [endAngle=Math.PI]
                   * The ending angle of the polar series.
                   */
                  endAngle: 'number',
  
                  /**
                   * @cfg {Number} [startRho=0]
                   * The starting radius of the polar series.
                   */
                  startRho: 'number',
  
                  /**
                   * @cfg {Number} [endRho=150]
                   * The ending radius of the polar series.
                   */
                  endRho: 'number',
  
                  /**
                   * @cfg {Number} [margin=0]
                   * Margin from the center of the pie. Used for donut.
                   */
                  margin: 'number',
  
                  /**
                   * @cfg {Number} [thickness=0]
                   * The thickness of the 3D pie part.
                   */
                  thickness: 'number',
  
                  /**
                   * @cfg {Number} [bevelWidth=5]
                   * The size of the 3D pie bevel.
                   */
                  bevelWidth: 'number',
  
                  /**
                   * @cfg {Number} [distortion=0]
                   * The distortion of the 3D pie part.
                   */
                  distortion: 'number',
  
                  /**
                   * @cfg {Object} [baseColor='white']
                   * The color of the 3D pie part before adding the 3D effect.
                   */
                  baseColor: 'color',
  
                  /**
                   * @cfg {Number} [colorSpread=1]
                   * An attribute used to control how flat the gradient of the sprite looks.
                   * A value of 0 essentially means no gradient (flat color).
                   */
                  colorSpread: 'number',
  
                  /**
                   * @cfg {Number} [baseRotation=0]
                   * The starting rotation of the polar series.
                   */
                  baseRotation: 'number',
  
                  /**
                   * @cfg {String} [part='top']
                   * The part of the 3D Pie represented by the sprite.
                   */
                  part: 'enums(top,bottom,start,end,innerFront,innerBack,outerFront,outerBack)',
  
                  /**
                   * @cfg {String} [label='']
                   * The label associated with the 'top' part of the sprite.
                   */
                  label: 'string'
              },
              aliases: {
                  rho: 'endRho'
              },
              triggers: {
                  centerX: 'path,bbox',
                  centerY: 'path,bbox',
                  startAngle: 'path,partZIndex',
                  endAngle: 'path,partZIndex',
                  startRho: 'path',
                  endRho: 'path,bbox',
                  margin: 'path,bbox',
                  thickness: 'path',
                  distortion: 'path',
                  baseRotation: 'path,partZIndex',
                  baseColor: 'partZIndex,partColor',
                  colorSpread: 'partColor',
                  part: 'path,partZIndex',
                  globalAlpha: 'canvas,alpha',
                  fillOpacity: 'canvas,alpha'
              },
              defaults: {
                  centerX: 0,
                  centerY: 0,
                  startAngle: Math.PI * 2,
                  endAngle: Math.PI * 2,
                  startRho: 0,
                  endRho: 150,
                  margin: 0,
                  thickness: 35,
                  distortion: 0.5,
                  baseRotation: 0,
                  baseColor: 'white',
                  colorSpread: 1,
                  miterLimit: 1,
                  bevelWidth: 5,
                  strokeOpacity: 0,
                  part: 'top',
                  label: ''
              },
              updaters: {
                  alpha: 'alphaUpdater',
                  partColor: 'partColorUpdater',
                  partZIndex: 'partZIndexUpdater'
              }
          }
      },
  
      bevelParams: [],
  
      constructor: function (config) {
          this.callParent([config]);
  
          this.bevelGradient = new Ext.draw.gradient.Linear({
              stops: [{
                  offset: 0,
                  color: 'rgba(255,255,255,0)'
              }, {
                  offset: 0.7,
                  color: 'rgba(255,255,255,0.6)'
              }, {
                  offset: 1,
                  color: 'rgba(255,255,255,0)'
              }]
          });
      },
  
      alphaUpdater: function (attr) {
          var me = this,
              opacity = attr.globalAlpha,
              fillOpacity = attr.fillOpacity,
              oldOpacity = me.oldOpacity,
              oldFillOpacity = me.oldFillOpacity;
  
          // Update the path when the sprite becomes translucent or completely opaque.
          if ((opacity !== oldOpacity && (opacity === 1 || oldOpacity === 1)) ||
              (fillOpacity !== oldFillOpacity && (fillOpacity === 1 || oldFillOpacity === 1))) {
              me.scheduleUpdater(attr, 'path', ['globalAlpha']);
              me.oldOpacity = opacity;
              me.oldFillOpacity = fillOpacity;
          }
      },
  
      partColorUpdater: function (attr) {
          var color = Ext.util.Color.fly(attr.baseColor),
              colorString = color.toString(),
              colorSpread = attr.colorSpread,
              fillStyle;
  
          switch (attr.part) {
              case 'top':
                  fillStyle = new Ext.draw.gradient.Radial({
                      start: {
                          x: 0,
                          y: 0,
                          r: 0
                      },
                      end: {
                          x: 0,
                          y: 0,
                          r: 1
                      },
                      stops: [{
                          offset: 0,
                          color: color.createLighter(0.1 * colorSpread)
                      }, {
                          offset: 1,
                          color: color.createDarker(0.1 * colorSpread)
                      }]
                  });
                  break;
              case 'bottom':
                  fillStyle =  new Ext.draw.gradient.Radial({
                      start: {
                          x: 0,
                          y: 0,
                          r: 0
                      },
                      end: {
                          x: 0,
                          y: 0,
                          r: 1
                      },
                      stops: [{
                          offset: 0,
                          color: color.createDarker(0.2 * colorSpread)
                      }, {
                          offset: 1,
                          color: color.toString()
                      }]
                  });
                  break;
              case 'outerFront':
              case 'outerBack':
                  fillStyle =  new Ext.draw.gradient.Linear({
                      stops: [{
                          offset: 0,
                          color: color.createDarker(0.15 * colorSpread).toString()
                      }, {
                          offset: 0.3,
                          color: colorString
                      }, {
                          offset: 0.8,
                          color: color.createLighter(0.2 * colorSpread).toString()
                      }, {
                          offset: 1,
                          color: color.createDarker(0.25 * colorSpread).toString()
                      }]
                  });
                  break;
              case 'start':
                  fillStyle = new Ext.draw.gradient.Linear({
                      stops: [{
                          offset: 0,
                          color: color.createDarker(0.1 * colorSpread).toString()
                      }, {
                          offset: 1,
                          color: color.createLighter(0.2 * colorSpread).toString()
                      }]
                  });
                  break;
              case 'end':
                  fillStyle = new Ext.draw.gradient.Linear({
                      stops: [{
                          offset: 0,
                          color: color.createDarker(0.1 * colorSpread).toString()
                      }, {
                          offset: 1,
                          color: color.createLighter(0.2 * colorSpread).toString()
                      }]
                  });
                  break;
              case 'innerFront':
              case 'innerBack':
                  fillStyle = new Ext.draw.gradient.Linear({
                      stops: [{
                          offset: 0,
                          color: color.createDarker(0.1 * colorSpread).toString()
                      }, {
                          offset: 0.2,
                          color: color.createLighter(0.2 * colorSpread).toString()
                      }, {
                          offset: 0.7,
                          color: colorString
                      }, {
                          offset: 1,
                          color: color.createDarker(0.1 * colorSpread).toString()
                      }]
                  });
                  break;
          }
  
          attr.fillStyle = fillStyle;
          attr.canvasAttributes.fillStyle = fillStyle;
      },
  
      partZIndexUpdater: function (attr) {
          var normalize = Ext.draw.sprite.AttributeParser.angle,
              rotation = attr.baseRotation,
              startAngle = attr.startAngle,
              endAngle = attr.endAngle,
              depth;
  
          switch (attr.part) {
              case 'top':
                  attr.zIndex = 6;
                  break;
              case 'outerFront':
                  startAngle = normalize(startAngle + rotation);
                  endAngle   = normalize(endAngle   + rotation);
                  if (startAngle >= 0 && endAngle < 0) {
                      depth = Math.sin(startAngle);
                  } else if (startAngle <= 0 && endAngle > 0) {
                      depth = Math.sin(endAngle);
                  } else if (startAngle >= 0 && endAngle > 0) {
                      if (startAngle > endAngle) {
                          depth = 0;
                      } else {
                          depth = Math.max(Math.sin(startAngle), Math.sin(endAngle));
                      }
                  } else {
                      depth = 1;
                  }
                  attr.zIndex = 4 + depth;
                  break;
              case 'outerBack':
                  attr.zIndex = 1;
                  break;
              case 'start':
                  attr.zIndex = 4 + Math.sin(normalize(startAngle + rotation));
                  break;
              case 'end':
                  attr.zIndex = 4 + Math.sin(normalize(endAngle + rotation));
                  break;
              case 'innerFront':
                  attr.zIndex = 2;
                  break;
              case 'innerBack':
                  attr.zIndex = 4 + Math.sin(normalize((startAngle + endAngle) / 2 + rotation));
                  break;
              case 'bottom':
                  attr.zIndex = 0;
                  break;
          }
          attr.dirtyZIndex = true;
      },
  
      updatePlainBBox: function (plain) {
          var attr = this.attr,
              part = attr.part,
              baseRotation = attr.baseRotation,
              centerX = attr.centerX,
              centerY = attr.centerY,
              rho, angle, x, y, sin, cos;
  
          if (part === 'start') {
              angle = attr.startAngle + baseRotation;
          } else if (part === 'end') {
              angle = attr.endAngle + baseRotation;
          }
  
          if (Ext.isNumber(angle)) {
              sin = Math.sin(angle);
              cos = Math.cos(angle);
  
              x = Math.min(
                  centerX + cos * attr.startRho,
                  centerX + cos * attr.endRho
              );
              y = centerY + sin * attr.startRho * attr.distortion;
  
              plain.x = x;
              plain.y = y;
              plain.width = cos * (attr.endRho - attr.startRho);
              plain.height = attr.thickness + sin * (attr.endRho - attr.startRho) * 2;
  
              return;
          }
  
          if (part === 'innerFront' || part === 'innerBack') {
              rho = attr.startRho;
          } else {
              rho = attr.endRho;
          }
  
          plain.width = rho * 2;
          plain.height = rho * attr.distortion * 2 + attr.thickness;
          plain.x = attr.centerX - rho;
          plain.y = attr.centerY - rho * attr.distortion;
      },
  
      updateTransformedBBox: function (transform) {
          if (this.attr.part === 'start' || this.attr.part === 'end') {
              return this.callParent(arguments);
          }
          return this.updatePlainBBox(transform);
      },
  
      updatePath: function (path) {
          if (!this.attr.globalAlpha) {
              return;
          }
          if (this.attr.endAngle < this.attr.startAngle) {
              return;
          }
          this[this.attr.part + 'Renderer'](path);
      },
  
      render: function (surface, ctx) {
          var me = this,
              attr = me.attr;
  
          if (!attr.globalAlpha || Ext.Number.isEqual(attr.startAngle, attr.endAngle, 1e-8)) {
              return;
          }
          me.callParent([surface, ctx]);
          me.bevelRenderer(surface, ctx);
  
          // Only the top part will have the label attribute (set by the series).
          if (attr.label && me.getMarker('labels')) {
              me.placeLabel();
          }
      },
  
      placeLabel: function () {
          var me = this,
              attr = me.attr,
              attributeId = attr.attributeId,
              margin = attr.margin,
              distortion = attr.distortion,
              centerX = attr.centerX,
              centerY = attr.centerY,
              baseRotation = attr.baseRotation,
              startAngle = attr.startAngle + baseRotation,
              endAngle = attr.endAngle + baseRotation,
              midAngle = (startAngle + endAngle) / 2,
              startRho = attr.startRho + margin,
              endRho = attr.endRho + margin,
              midRho = (startRho + endRho) / 2,
              sin = Math.sin(midAngle),
              cos = Math.cos(midAngle),
              surfaceMatrix = me.surfaceMatrix,
              label = me.getMarker('labels'),
              labelTpl = label.getTemplate(),
              calloutLine = labelTpl.getCalloutLine(),
              calloutLineLength = calloutLine && calloutLine.length || 40,
              labelCfg = {},
              x, y;
  
          surfaceMatrix.appendMatrix(attr.matrix);
  
          labelCfg.text = attr.label;
  
          x = centerX + cos * midRho;
          y = centerY + sin * midRho * distortion;
  
          labelCfg.x = surfaceMatrix.x(x, y);
          labelCfg.y = surfaceMatrix.y(x, y);
  
          x = centerX + cos * endRho;
          y = centerY + sin * endRho * distortion;
  
          labelCfg.calloutStartX = surfaceMatrix.x(x, y);
          labelCfg.calloutStartY = surfaceMatrix.y(x, y);
  
          x = centerX + cos * (endRho + calloutLineLength);
          y = centerY + sin * (endRho + calloutLineLength) * distortion;
          labelCfg.calloutPlaceX = surfaceMatrix.x(x, y);
          labelCfg.calloutPlaceY = surfaceMatrix.y(x, y);
  
          labelCfg.calloutWidth = 2;
  
          me.putMarker('labels', labelCfg, attributeId);
  
          me.putMarker('labels', {
              callout: 1
          }, attributeId);
      },
  
      bevelRenderer: function (surface, ctx) {
          var me = this,
              attr = me.attr,
              bevelWidth = attr.bevelWidth,
              params = me.bevelParams,
              i;
  
          for (i = 0; i < params.length; i++) {
              ctx.beginPath();
              ctx.ellipse.apply(ctx, params[i]);
              ctx.save();
              ctx.lineWidth = bevelWidth;
              ctx.strokeOpacity = bevelWidth ? 1 : 0;
              ctx.strokeGradient = me.bevelGradient;
              ctx.stroke(attr);
              ctx.restore();
          }
      },
  
      lidRenderer: function (path, thickness) {
          var attr = this.attr,
              margin = attr.margin,
              distortion = attr.distortion,
              centerX = attr.centerX,
              centerY = attr.centerY,
              baseRotation = attr.baseRotation,
              startAngle = attr.startAngle + baseRotation,
              endAngle = attr.endAngle + baseRotation,
              midAngle = (startAngle + endAngle) / 2,
              startRho = attr.startRho,
              endRho = attr.endRho,
              sinEnd = Math.sin(endAngle),
              cosEnd = Math.cos(endAngle);
  
          centerX += Math.cos(midAngle) * margin;
          centerY += Math.sin(midAngle) * margin * distortion;
  
          path.ellipse(
              centerX, centerY + thickness,
              startRho, startRho * distortion,
              0, startAngle, endAngle, false
          );
          path.lineTo(
              centerX + cosEnd * endRho,
              centerY + thickness + sinEnd * endRho * distortion
          );
          path.ellipse(
              centerX, centerY + thickness,
              endRho, endRho * distortion,
              0, endAngle, startAngle, true
          );
          path.closePath();
      },
  
      topRenderer: function (path) {
          this.lidRenderer(path, 0);
      },
  
      bottomRenderer: function (path) {
          var attr = this.attr,
              none = Ext.util.Color.RGBA_NONE;
  
          if (attr.globalAlpha < 1 || attr.fillOpacity < 1 || attr.shadowColor !== none) {
              this.lidRenderer(path, attr.thickness);
          }
      },
  
      sideRenderer: function (path, position) {
          var attr = this.attr,
              margin = attr.margin,
              centerX = attr.centerX,
              centerY = attr.centerY,
              distortion = attr.distortion,
              baseRotation = attr.baseRotation,
              startAngle = attr.startAngle + baseRotation,
              endAngle = attr.endAngle + baseRotation,
              isFullPie = (!attr.startAngle && Ext.Number.isEqual(Math.PI * 2, attr.endAngle, 0.0000001)),
              thickness = attr.thickness,
              startRho = attr.startRho,
              endRho = attr.endRho,
              angle = (position === 'start' && startAngle) ||
                      (position === 'end' && endAngle),
              sin = Math.sin(angle),
              cos = Math.cos(angle),
              isTranslucent = attr.globalAlpha < 1,
              isVisible = position === 'start' && cos < 0 ||
                          position === 'end' && cos > 0 ||
                          isTranslucent,
              midAngle;
  
          if (isVisible && !isFullPie) {
              midAngle = (startAngle + endAngle) / 2;
              centerX += Math.cos(midAngle) * margin;
              centerY += Math.sin(midAngle) * margin * distortion;
              path.moveTo(
                  centerX + cos * startRho,
                  centerY + sin * startRho * distortion
              );
              path.lineTo(
                  centerX + cos * endRho,
                  centerY + sin * endRho * distortion
              );
              path.lineTo(
                  centerX + cos * endRho,
                  centerY + sin * endRho * distortion + thickness
              );
              path.lineTo(
                  centerX + cos * startRho,
                  centerY + sin * startRho * distortion + thickness
              );
              path.closePath();
          }
      },
  
      startRenderer: function (path) {
          this.sideRenderer(path, 'start');
      },
  
      endRenderer: function (path) {
          this.sideRenderer(path, 'end');
      },
  
      rimRenderer: function (path, radius, isDonut, isFront) {
          var me = this,
              attr = me.attr,
              margin = attr.margin,
              centerX = attr.centerX,
              centerY = attr.centerY,
              distortion = attr.distortion,
              baseRotation = attr.baseRotation,
              normalize = Ext.draw.sprite.AttributeParser.angle,
              startAngle = attr.startAngle + baseRotation,
              endAngle = attr.endAngle + baseRotation,
              // It's critical to use non-normalized start and end angles
              // for middle angle calculation. Consider a situation where the
              // start angle is +170 degrees and the end engle is -170 degrees
              // after normalization (the middle angle is 0 then, but it should be 180 degrees).
              midAngle = normalize((startAngle + endAngle) / 2),
              thickness = attr.thickness,
              isTranslucent = attr.globalAlpha < 1,
              isAllFront, isAllBack,
              params;
  
          me.bevelParams = [];
  
          startAngle = normalize(startAngle);
          endAngle = normalize(endAngle);
  
          centerX += Math.cos(midAngle) * margin;
          centerY += Math.sin(midAngle) * margin * distortion;
  
          isAllFront = startAngle >= 0 && endAngle >= 0;
          isAllBack = startAngle <= 0 && endAngle <= 0;
  
          function renderLeftFrontChunk() {
              path.ellipse(
                  centerX, centerY + thickness,
                  radius, radius * distortion,
                  0, Math.PI, startAngle, true
              );
              path.lineTo(
                  centerX + Math.cos(startAngle) * radius,
                  centerY + Math.sin(startAngle) * radius * distortion
              );
              params = [
                  centerX, centerY,
                  radius, radius * distortion,
                  0, startAngle, Math.PI, false
              ];
              if (!isDonut) {
                  me.bevelParams.push(params);
              }
              path.ellipse.apply(path, params);
              path.closePath();
          }
  
          function renderRightFrontChunk() {
              path.ellipse(
                  centerX, centerY + thickness,
                  radius, radius * distortion,
                  0, 0, endAngle, false
              );
              path.lineTo(
                  centerX + Math.cos(endAngle) * radius,
                  centerY + Math.sin(endAngle) * radius * distortion
              );
              params = [
                  centerX, centerY,
                  radius, radius * distortion,
                  0, endAngle, 0, true
              ];
              if (!isDonut) {
                  me.bevelParams.push(params);
              }
              path.ellipse.apply(path, params);
              path.closePath();
          }
  
          function renderLeftBackChunk() {
              path.ellipse(
                  centerX, centerY + thickness,
                  radius, radius * distortion,
                  0, Math.PI, endAngle, false
              );
              path.lineTo(
                  centerX + Math.cos(endAngle) * radius,
                  centerY + Math.sin(endAngle) * radius * distortion
              );
              params = [
                  centerX, centerY,
                  radius, radius * distortion,
                  0, endAngle, Math.PI, true
              ];
              if (isDonut) {
                  me.bevelParams.push(params);
              }
              path.ellipse.apply(path, params);
              path.closePath();
          }
  
  
          function renderRightBackChunk() {
              path.ellipse(
                  centerX, centerY + thickness,
                  radius, radius * distortion,
                  0, startAngle, 0, false
              );
              path.lineTo(
                  centerX + radius,
                  centerY
              );
              params = [
                  centerX, centerY,
                  radius, radius * distortion,
                  0, 0, startAngle, true
              ];
              if (isDonut) {
                  me.bevelParams.push(params);
              }
              path.ellipse.apply(path, params);
              path.closePath();
          }
  
          if (isFront) {
              if (!isDonut || isTranslucent) {
                  if (startAngle >= 0 && endAngle < 0) {
                      renderLeftFrontChunk();
                  } else if (startAngle <= 0 && endAngle > 0) {
                      renderRightFrontChunk();
                  } else if (startAngle <= 0 && endAngle < 0) {
                      if (startAngle > endAngle) {
                          path.ellipse(
                              centerX, centerY + thickness,
                              radius, radius * distortion,
                              0, 0, Math.PI, false
                          );
                          path.lineTo(
                              centerX - radius,
                              centerY
                          );
                          params = [
                              centerX, centerY,
                              radius, radius * distortion,
                              0, Math.PI, 0, true
                          ];
                          if (!isDonut) {
                              me.bevelParams.push(params);
                          }
                          path.ellipse.apply(path, params);
                          path.closePath();
                      }
                  } else { // startAngle >= 0 && endAngle > 0
                      // obtuse horseshoe-like slice with the gap facing forward
                      if (startAngle > endAngle) {
                          renderLeftFrontChunk();
                          renderRightFrontChunk();
                      } else { // acute slice facing forward
                          params = [
                              centerX, centerY,
                              radius, radius * distortion,
                              0, startAngle, endAngle, false
                          ];
                          if (isAllFront && !isDonut || isAllBack && isDonut) {
                              me.bevelParams.push(params);
                          }
                          path.ellipse.apply(path, params);
                          path.lineTo(
                              centerX + Math.cos(endAngle) * radius,
                              centerY + Math.sin(endAngle) * radius * distortion + thickness
                          );
                          path.ellipse(
                              centerX, centerY + thickness,
                              radius, radius * distortion,
                              0, endAngle, startAngle, true
                          );
                          path.closePath();
                      }
                  }
              }
          } else {
              if (isDonut || isTranslucent) {
                  if (startAngle >= 0 && endAngle < 0) {
                      renderLeftBackChunk();
                  } else if (startAngle <= 0 && endAngle > 0) {
                      renderRightBackChunk();
                  } else if (startAngle <= 0 && endAngle < 0) {
                      if (startAngle > endAngle) {
                          renderLeftBackChunk();
                          renderRightBackChunk();
                      } else {
                          path.ellipse(
                              centerX, centerY + thickness,
                              radius, radius * distortion,
                              0, startAngle, endAngle, false
                          );
                          path.lineTo(
                              centerX + Math.cos(endAngle) * radius,
                              centerY + Math.sin(endAngle) * radius * distortion
                          );
                          params = [
                              centerX, centerY,
                              radius, radius * distortion,
                              0, endAngle, startAngle, true
                          ];
                          if (isDonut) {
                              me.bevelParams.push(params);
                          }
                          path.ellipse.apply(path, params);
                          path.closePath();
                      }
                  } else { // startAngle >= 0 && endAngle > 0
                      if (startAngle > endAngle) {
                          path.ellipse(
                              centerX, centerY + thickness,
                              radius, radius * distortion,
                              0, -Math.PI, 0, false
                          );
                          path.lineTo(
                              centerX + radius,
                              centerY
                          );
                          params = [
                              centerX, centerY,
                              radius, radius * distortion,
                              0, 0, -Math.PI, true
                          ];
                          if (isDonut) {
                              me.bevelParams.push(params);
                          }
                          path.ellipse.apply(path, params);
                          path.closePath();
                      }
                  }
              }
          }
      },
  
      innerFrontRenderer: function (path) {
          this.rimRenderer(path, this.attr.startRho, true, true);
      },
  
      innerBackRenderer: function (path) {
          this.rimRenderer(path, this.attr.startRho, true, false);
      },
  
      outerFrontRenderer: function (path) {
          this.rimRenderer(path, this.attr.endRho, false, true);
      },
  
      outerBackRenderer: function (path) {
          this.rimRenderer(path, this.attr.endRho, false, false);
      }
  });