当前位置: 首页>>代码示例>>C++>>正文


C++ QPolygonF::data方法代码示例

本文整理汇总了C++中QPolygonF::data方法的典型用法代码示例。如果您正苦于以下问题:C++ QPolygonF::data方法的具体用法?C++ QPolygonF::data怎么用?C++ QPolygonF::data使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在QPolygonF的用法示例。


在下文中一共展示了QPolygonF::data方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: clipRect

QgsConstWkbPtr QgsSymbolV2::_getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr wkbPtr, bool clipToExtent )
{
  QgsWKBTypes::Type wkbType = wkbPtr.readHeader();
  unsigned int nPoints;
  wkbPtr >> nPoints;

  const QgsCoordinateTransform* ct = context.coordinateTransform();
  const QgsMapToPixel& mtp = context.mapToPixel();

  //apply clipping for large lines to achieve a better rendering performance
  if ( clipToExtent && nPoints > 1 )
  {
    const QgsRectangle& e = context.extent();
    double cw = e.width() / 10;
    double ch = e.height() / 10;
    QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
    wkbPtr -= 1 + 2 * sizeof( int );
    wkbPtr = QgsClipper::clippedLineWKB( wkbPtr, clipRect, pts );
  }
  else
  {
    pts.resize( nPoints );

    int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double );
    Q_ASSERT( skipZM >= 0 );

    QPointF *ptr = pts.data();
    for ( unsigned int i = 0; i < nPoints; ++i, ++ptr )
    {
      wkbPtr >> ptr->rx() >> ptr->ry();
      wkbPtr += skipZM;
    }
  }

  //transform the QPolygonF to screen coordinates
  if ( ct )
  {
    ct->transformPolygon( pts );
  }

  QPointF *ptr = pts.data();
  for ( int i = 0; i < pts.size(); ++i, ++ptr )
  {
    mtp.transformInPlace( ptr->rx(), ptr->ry() );
  }

  return wkbPtr;
}
开发者ID:RobDeBagel,项目名称:QGIS,代码行数:48,代码来源:qgssymbolv2.cpp

示例2: fitCurve

    const QwtArray<QwtDoublePoint> & points) const
#else
QPolygonF QwtSplineCurveFitter::fitCurve(const QPolygonF &points) const
#endif
{
    const int size = (int)points.size();
    if ( size <= 2 )
        return points;

    FitMode fitMode = d_data->fitMode;
    if ( fitMode == Auto )
    {
        fitMode = Spline;

        const QwtDoublePoint *p = points.data();
        for ( int i = 1; i < size; i++ )
        {
            if ( p[i].x() <= p[i-1].x() )
            {
                fitMode = ParametricSpline;
                break;
            }
        };
    }

    if ( fitMode == ParametricSpline )
        return fitParametric(points);
    else
        return fitSpline(points);
}
开发者ID:BijanZarif,项目名称:coolfluid3,代码行数:30,代码来源:qwt_curve_fitter.cpp

示例3: fromConformalInverted

void UwMath::fromConformalInverted(QPolygonF &object) {
    QPointF * data = object.data();

    for(int i = 0; i < object.size(); i++) {
        data[i].setX(UwMath::toDegrees(object.at(i).x()));
        data[i].setY(UwMath::fromMercator(object.at(i).y() * (-1)));
    }
}
开发者ID:pcannon67,项目名称:devel,代码行数:8,代码来源:uwmath.cpp

示例4: toConformal

/** Converts a list of points from degrees to a conformal
  * point in Mercator projection
  * @param points in longitude, latitude given in degrees (DD)
  * @return conformal points in radians
  */
void UwMath::toConformal(QPolygonF &object) {
    QPointF * data = object.data();

    for(int i = 0; i < object.size(); i++) {
        data[i].setX(UwMath::toRadians(object.at(i).x()));
        data[i].setY(UwMath::toMercator(object.at(i).y()));
    }
}
开发者ID:pcannon67,项目名称:devel,代码行数:13,代码来源:uwmath.cpp

示例5: fitParametric

QPolygonF QwtSplineCurveFitter::fitParametric( const QPolygonF &points ) const
{
    int i;
    const int size = points.size();

    QPolygonF fittedPoints( d_data->splineSize );
    QPolygonF splinePointsX( size );
    QPolygonF splinePointsY( size );

    const QPointF *p = points.data();
    QPointF *spX = splinePointsX.data();
    QPointF *spY = splinePointsY.data();

    double param = 0.0;
    for ( i = 0; i < size; i++ )
    {
        const double x = p[i].x();
        const double y = p[i].y();
        if ( i > 0 )
        {
            const double delta = qSqrt( qwtSqr( x - spX[i-1].y() )
                      + qwtSqr( y - spY[i-1].y() ) );
            param += qMax( delta, 1.0 );
        }
        spX[i].setX( param );
        spX[i].setY( x );
        spY[i].setX( param );
        spY[i].setY( y );
    }

    d_data->spline.setPoints( splinePointsX );
    if ( !d_data->spline.isValid() )
        return points;

    const double deltaX =
        splinePointsX[size - 1].x() / ( d_data->splineSize - 1 );
    for ( i = 0; i < d_data->splineSize; i++ )
    {
        const double dtmp = i * deltaX;
        fittedPoints[i].setX( qRound( d_data->spline.value( dtmp ) ) );
    }

    d_data->spline.setPoints( splinePointsY );
    if ( !d_data->spline.isValid() )
        return points;

    const double deltaY =
        splinePointsY[size - 1].x() / ( d_data->splineSize - 1 );
    for ( i = 0; i < d_data->splineSize; i++ )
    {
        const double dtmp = i * deltaY;
        fittedPoints[i].setY( qRound( d_data->spline.value( dtmp ) ) );
    }

    return fittedPoints;
}
开发者ID:PrincetonPAVE,项目名称:old_igvc,代码行数:56,代码来源:qwt_curve_fitter.cpp

示例6: bezier_fit_cubic_single

QPolygonF bezier_fit_cubic_single( const QPolygonF& data, double error )
{
  QPolygonF out(4);
  const int retn = sp_bezier_fit_cubic(out.data(), data.data(),
				       data.count(), error);
  if( retn >= 0 )
    return out;
  else
    return QPolygonF();
}
开发者ID:Felipeasg,项目名称:veusz,代码行数:10,代码来源:beziers_qtwrap.cpp

示例7: test_arc

// we need a higher threshold for failure here than in the above tests, as this basically draws
// a very thin outline, where the discretization in the new tesselator shows
bool test_arc(const QPolygonF &poly, bool winding)
{
    QVector<XTrapezoid> traps;
    qreal area1 = 0;
    qreal area2 = 0;

    old_tesselate_polygon(&traps, poly.data(), poly.size(), winding);
    area1 = compute_area_for_x(traps);

    traps.clear();

    test_tesselate_polygon(&traps, poly.data(), poly.size(), winding);
    area2 = compute_area_for_x(traps);

    bool result = (area2 - area1 < .02);
    if (!result && area1)
        result = (qAbs(area1 - area2)/area1 < .02);

    return result;
}
开发者ID:KDE,项目名称:android-qt,代码行数:22,代码来源:tst_tessellator.cpp

示例8: transformPolygon

void QgsCoordinateTransform::transformPolygon( QPolygonF &poly, TransformDirection direction ) const
{
  if ( !d->mIsValid || d->mShortCircuit )
  {
    return;
  }

  //create x, y arrays
  int nVertices = poly.size();

  QVector<double> x( nVertices );
  QVector<double> y( nVertices );
  QVector<double> z( nVertices );
  double *destX = x.data();
  double *destY = y.data();
  double *destZ = z.data();

  const QPointF *polyData = poly.constData();
  for ( int i = 0; i < nVertices; ++i )
  {
    *destX++ = polyData->x();
    *destY++ = polyData->y();
    *destZ++ = 0;
    polyData++;
  }

  try
  {
    transformCoords( nVertices, x.data(), y.data(), z.data(), direction );
  }
  catch ( const QgsCsException & )
  {
    // rethrow the exception
    QgsDebugMsg( QStringLiteral( "rethrowing exception" ) );
    throw;
  }

  QPointF *destPoint = poly.data();
  const double *srcX = x.constData();
  const double *srcY = y.constData();
  for ( int i = 0; i < nVertices; ++i )
  {
    destPoint->rx() = *srcX++;
    destPoint->ry() = *srcY++;
    destPoint++;
  }
}
开发者ID:boundlessgeo,项目名称:QGIS,代码行数:47,代码来源:qgscoordinatetransform.cpp

示例9: bezier_fit_cubic_multi

QPolygonF bezier_fit_cubic_multi( const QPolygonF& data, double error,
				  unsigned max_beziers )
{
  QPolygonF out(4*max_beziers);
  const int retn = sp_bezier_fit_cubic_r(out.data(), data.data(),
					 data.count(), error,
					 max_beziers);

  if( retn >= 0 )
    {
      // get rid of unused points
      if( retn*4 < out.count() )
	out.remove( retn*4, out.count()-retn*4 );
      return out;
    }
  else
    return QPolygonF();
}
开发者ID:Felipeasg,项目名称:veusz,代码行数:18,代码来源:beziers_qtwrap.cpp

示例10: drawDots

/*!
  Draw dots

  \param painter Painter
  \param xMap x map
  \param yMap y map
  \param canvasRect Contents rect of the canvas
  \param from index of the first point to be painted
  \param to index of the last point to be painted

  \sa draw(), drawCurve(), drawSticks(), drawLines(), drawSteps()
*/
void QwtPlotCurve::drawDots( QPainter *painter,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    const QRectF &canvasRect, int from, int to ) const
{
    const bool doFill = d_data->brush.style() != Qt::NoBrush;
    const bool doAlign = QwtPainter::roundingAlignment( painter );

    QPolygonF polyline;
    if ( doFill )
        polyline.resize( to - from + 1 );

    QPointF *points = polyline.data();

    for ( int i = from; i <= to; i++ )
    {
        const QPointF sample = d_series->sample( i );
        double xi = xMap.transform( sample.x() );
        double yi = yMap.transform( sample.y() );
        if ( doAlign )
        {
            xi = qRound( xi );
            yi = qRound( yi );
        }

        QwtPainter::drawPoint( painter, QPointF( xi, yi ) );

        if ( doFill )
        {
            points[i - from].rx() = xi;
            points[i - from].ry() = yi;
        }
    }

    if ( doFill )
    {
        if ( d_data->paintAttributes & ClipPolygons )
            polyline = QwtClipper::clipPolygonF( canvasRect, polyline );

        fillCurve( painter, xMap, yMap, polyline );
    }
}
开发者ID:PrincetonPAVE,项目名称:old_igvc,代码行数:53,代码来源:qwt_plot_curve.cpp

示例11: sipConvertFromVoidPtr

static PyObject *meth_QPolygonF_data(PyObject *sipSelf, PyObject *sipArgs)
{
    PyObject *sipParseErr = NULL;

    {
        QPolygonF *sipCpp;

        if (sipParseArgs(&sipParseErr, sipArgs, "B", &sipSelf, sipType_QPolygonF, &sipCpp))
        {
            void*sipRes;

            sipRes = sipCpp->data();

            return sipConvertFromVoidPtr(sipRes);
        }
    }

    /* Raise an exception if the arguments couldn't be parsed. */
    sipNoMethod(sipParseErr, sipName_QPolygonF, sipName_data, doc_QPolygonF_data);

    return NULL;
}
开发者ID:rff255,项目名称:python-qt5,代码行数:22,代码来源:sipQtGuiQPolygonF.cpp

示例12: drawTube

/*!
  Draw a tube

  Builds 2 curves from the upper and lower limits of the intervals
  and draws them with the pen(). The area between the curves is
  filled with the brush().

  \param painter Painter
  \param xMap Maps x-values into pixel coordinates.
  \param yMap Maps y-values into pixel coordinates.
  \param canvasRect Contents rect of the canvas
  \param from Index of the first sample to be painted
  \param to Index of the last sample to be painted. If to < 0 the
         series will be painted to its last sample.

  \sa drawSeries(), drawSymbols()
*/
void QwtPlotIntervalCurve::drawTube( QPainter *painter,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    const QRectF &canvasRect, int from, int to ) const
{
    const bool doAlign = QwtPainter::roundingAlignment( painter );

    painter->save();

    const size_t size = to - from + 1;
    QPolygonF polygon( 2 * size );
    QPointF *points = polygon.data();

    for ( uint i = 0; i < size; i++ )
    {
        QPointF &minValue = points[i];
        QPointF &maxValue = points[2 * size - 1 - i];

        const QwtIntervalSample intervalSample = sample( from + i );
        if ( orientation() == Qt::Vertical )
        {
            double x = xMap.transform( intervalSample.value );
            double y1 = yMap.transform( intervalSample.interval.minValue() );
            double y2 = yMap.transform( intervalSample.interval.maxValue() );
            if ( doAlign )
            {
                x = qRound( x );
                y1 = qRound( y1 );
                y2 = qRound( y2 );
            }

            minValue.rx() = x;
            minValue.ry() = y1;
            maxValue.rx() = x;
            maxValue.ry() = y2;
        }
        else
        {
            double y = yMap.transform( intervalSample.value );
            double x1 = xMap.transform( intervalSample.interval.minValue() );
            double x2 = xMap.transform( intervalSample.interval.maxValue() );
            if ( doAlign )
            {
                y = qRound( y );
                x1 = qRound( x1 );
                x2 = qRound( x2 );
            }

            minValue.rx() = x1;
            minValue.ry() = y;
            maxValue.rx() = x2;
            maxValue.ry() = y;
        }
    }

    if ( d_data->brush.style() != Qt::NoBrush )
    {
        painter->setPen( QPen( Qt::NoPen ) );
        painter->setBrush( d_data->brush );

        if ( d_data->paintAttributes & ClipPolygons )
        {
            const qreal m = 1.0;
            const QPolygonF p = QwtClipper::clipPolygonF( 
                canvasRect.adjusted(-m, -m, m, m), polygon, true );

            QwtPainter::drawPolygon( painter, p );
        }
        else
        {
            QwtPainter::drawPolygon( painter, polygon );
        }
    }

    if ( d_data->pen.style() != Qt::NoPen )
    {
        painter->setPen( d_data->pen );
        painter->setBrush( Qt::NoBrush );

        if ( d_data->paintAttributes & ClipPolygons )
        {
            QPolygonF p;

            p.resize( size );
//.........这里部分代码省略.........
开发者ID:1heinz,项目名称:TauLabs,代码行数:101,代码来源:qwt_plot_intervalcurve.cpp

示例13: drawCurve

// draw the ALT/SLOPE curve
void AllPlotSlopeCurve::drawCurve( QPainter *painter, int,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    const QRectF &, int from, int to ) const
{

    const QwtSeriesData<QPointF> *series = data();

    // parameter (will move to data

    // use sensible defaults
    double section_delta = 0.1;
    bool byDistance = true;

    switch (d_data->style) {

    // time-section is defined in minutes, distance-section in km
    case SlopeTime1 : { section_delta = 1.0; byDistance = false; break; }
    case SlopeTime2 : { section_delta = 5.0; byDistance = false; break; }
    case SlopeTime3 : { section_delta = 10.0; byDistance = false; break; }
    case SlopeDist1 : { section_delta = 0.1; byDistance = true; break; }
    case SlopeDist2 : { section_delta = 0.5; byDistance = true; break; }
    case SlopeDist3 : { section_delta = 1; byDistance = true; break; }
    }

    // create single polygons to be painted (in different colors depending on slope)
    QList<QPolygonF*> polygons;
    // store the polygon edge points (original coordinates) for slope/distance & m/time calculation
    QList<QPointF> calcPoints;

    // prepare Y-Axis baseline info for painting the polygon
    double baseline = d_data->baseline;
    if ( yMap.transformation() )
        baseline = yMap.transformation()->bounded( baseline );
    double refY = yMap.transform( baseline );
    double sectionStart = 0.0;
    QPolygonF *polygon;
    QPointF *points = NULL;
    for (int i = from; i <= to; i++ ) {
        const QPointF sample = series->sample( i );
        if (i == from) {
            // first polygon
            polygon = new QPolygonF (4);
            points = polygon->data();
            sectionStart = sample.x();
            double xi = xMap.transform( sample.x() );
            double yi = yMap.transform( sample.y() );
            points[0].rx() = xi;
            points[0].ry() = refY;
            points[1].rx() = xi;
            points[1].ry() = yi;
            // first point for slope/mperh calcuation
            QPointF calcPoint;
            calcPoint.rx() = sample.x();
            calcPoint.ry() = sample.y();
            calcPoints.append(calcPoint);
        };

        // we are in a section - so search for the end and if found close polygon
        if (points && sample.x() >= (sectionStart+section_delta)) {
            // we are at the end - close and create polygon and go to next
            double xi = xMap.transform( sample.x() );
            double yi = yMap.transform( sample.y() );
            points[2].rx() = xi;
            points[2].ry() = yi;
            points[3].rx() = xi;
            points[3].ry() = refY;
            // append to list
            polygons.append(polygon);
            // next point for slope/mperh calcuation
            QPointF calcPoint;
            calcPoint.rx() = sample.x();
            calcPoint.ry() = sample.y();
            calcPoints.append(calcPoint);

            // start the next polygon with the SAME point than the previous one to have a step-free graph
            polygon = new QPolygonF (4);
            points = polygon->data();
            sectionStart = sample.x();
            double xi2 = xMap.transform( sample.x() );
            double yi2 = yMap.transform( sample.y() );
            points[0].rx() = xi2;
            points[0].ry() = refY;
            points[1].rx() = xi2;
            points[1].ry() = yi2;
        }
        // last started polygon is not closed and painted by intent since it would be smaller than then the others
    }

    // paint the polygons & text per polygon
    int i = 0;
    foreach (QPolygonF *p, polygons) {

        double slope=0.0f; // slope of a section (byDistance = true)
        double mperh=0.0f; // meter per hour (climb or descent) (byDistance = false)
        QPointF point1 = calcPoints.at(i);
        QPointF point2 = calcPoints.at(i+1);

        QBrush brush;
        if (byDistance) {
//.........这里部分代码省略.........
开发者ID:cernst72,项目名称:GoldenCheetah,代码行数:101,代码来源:AllPlotSlopeCurve.cpp

示例14: clippedLineWKB

QgsConstWkbPtr QgsClipper::clippedLineWKB( QgsConstWkbPtr& wkbPtr, const QgsRectangle& clipExtent, QPolygonF& line )
{
  QgsWKBTypes::Type wkbType = wkbPtr.readHeader();

  int nPoints;
  wkbPtr >> nPoints;

  int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double );

  if ( static_cast<int>( nPoints * ( 2 * sizeof( double ) + skipZM ) ) > wkbPtr.remaining() )
  {
    QgsDebugMsg( QString( "%1 points exceed wkb length (%2>%3)" ).arg( nPoints ).arg( nPoints * ( 2 * sizeof( double ) + skipZM ) ).arg( wkbPtr.remaining() ) );
    return QgsConstWkbPtr( nullptr, 0 );
  }

  double p0x, p0y, p1x = 0.0, p1y = 0.0; //original coordinates
  double p1x_c, p1y_c; //clipped end coordinates
  double lastClipX = 0.0, lastClipY = 0.0; //last successfully clipped coords

  QPolygonF pts;
  wkbPtr -= sizeof( unsigned int );
  wkbPtr >> pts;
  nPoints = pts.size();

  line.clear();
  line.reserve( nPoints + 1 );

  QPointF *ptr = pts.data();

  for ( int i = 0; i < nPoints; ++i, ++ptr )
  {
    if ( i == 0 )
    {
      p1x = ptr->rx();
      p1y = ptr->ry();
      continue;
    }
    else
    {
      p0x = p1x;
      p0y = p1y;

      p1x = ptr->rx();
      p1y = ptr->ry();

      p1x_c = p1x;
      p1y_c = p1y;
      if ( clipLineSegment( clipExtent.xMinimum(), clipExtent.xMaximum(), clipExtent.yMinimum(), clipExtent.yMaximum(),
                            p0x, p0y, p1x_c,  p1y_c ) )
      {
        bool newLine = !line.isEmpty() && ( !qgsDoubleNear( p0x, lastClipX ) || !qgsDoubleNear( p0y, lastClipY ) );
        if ( newLine )
        {
          //add edge points to connect old and new line
          connectSeparatedLines( lastClipX, lastClipY, p0x, p0y, clipExtent, line );
        }
        if ( line.size() < 1 || newLine )
        {
          //add first point
          line << QPointF( p0x, p0y );
        }

        //add second point
        lastClipX = p1x_c;
        lastClipY = p1y_c;
        line << QPointF( p1x_c,  p1y_c );
      }
    }
  }
  return wkbPtr;
}
开发者ID:AM7000000,项目名称:QGIS,代码行数:71,代码来源:qgsclipper.cpp

示例15: fitCurve

/*!
  \param points Series of data points
  \return Curve points
*/
QPolygonF QwtWeedingCurveFitter::fitCurve( const QPolygonF &points ) const
{
    QStack<Line> stack;
    stack.reserve( 500 );

    const QPointF *p = points.data();
    const int nPoints = points.size();

    QVector<bool> usePoint( nPoints, false );

    double distToSegment;

    stack.push( Line( 0, nPoints - 1 ) );

    while ( !stack.isEmpty() )
    {
        const Line r = stack.pop();

        // initialize line segment
        const double vecX = p[r.to].x() - p[r.from].x();
        const double vecY = p[r.to].y() - p[r.from].y();

        const double vecLength = qSqrt( vecX * vecX + vecY * vecY );

        const double unitVecX = ( vecLength != 0.0 ) ? vecX / vecLength : 0.0;
        const double unitVecY = ( vecLength != 0.0 ) ? vecY / vecLength : 0.0;

        double maxDist = 0.0;
        int nVertexIndexMaxDistance = r.from + 1;
        for ( int i = r.from + 1; i < r.to; i++ )
        {
            //compare to anchor
            const double fromVecX = p[i].x() - p[r.from].x();
            const double fromVecY = p[i].y() - p[r.from].y();
            const double fromVecLength =
                qSqrt( fromVecX * fromVecX + fromVecY * fromVecY );

            if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 )
            {
                distToSegment = fromVecLength;
            }
            if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 )
            {
                distToSegment = fromVecLength;
            }
            else
            {
                const double toVecX = p[i].x() - p[r.to].x();
                const double toVecY = p[i].y() - p[r.to].y();
                const double toVecLength = qSqrt( toVecX * toVecX + toVecY * toVecY );
                const double s = toVecX * ( -unitVecX ) + toVecY * ( -unitVecY );
                if ( s < 0.0 )
                    distToSegment = toVecLength;
                else
                {
                    distToSegment = qSqrt( qFabs( toVecLength * toVecLength - s * s ) );
                }
            }

            if ( maxDist < distToSegment )
            {
                maxDist = distToSegment;
                nVertexIndexMaxDistance = i;
            }
        }
        if ( maxDist <= d_data->tolerance )
        {
            usePoint[r.from] = true;
            usePoint[r.to] = true;
        }
        else
        {
            stack.push( Line( r.from, nVertexIndexMaxDistance ) );
            stack.push( Line( nVertexIndexMaxDistance, r.to ) );
        }
    }

    int cnt = 0;

    QPolygonF stripped( nPoints );
    for ( int i = 0; i < nPoints; i++ )
    {
        if ( usePoint[i] )
            stripped[cnt++] = p[i];
    }
    stripped.resize( cnt );
    return stripped;
}
开发者ID:PrincetonPAVE,项目名称:old_igvc,代码行数:92,代码来源:qwt_curve_fitter.cpp


注:本文中的QPolygonF::data方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。