Пример #1
0
//Returns the lattice cell containing the relative position pos.
inline TPoint TCacheResource::getCellPos(const TPointD &pos) const
{
	TPoint cellIndex(
		tfloor(pos.x / (double)latticeStep),
		tfloor(pos.y / (double)latticeStep));
	return TPoint(cellIndex.x * latticeStep, cellIndex.y * latticeStep);
}
Пример #2
0
TColor TPatternParquet::evaluate (const TVector& rktPOINT) const
{

  TScalar  tValue;
  TColor   tRet;
  TScalar  tX  = rktPOINT.x()/3;
  TScalar  tY  = rktPOINT.y()/3;
  TScalar  tZ  = rktPOINT.z()/3;
  int      iX  = ((int) tfloor (rktPOINT.x() / 8.0)) & 7;
  int      iZ  = ((int) tfloor (rktPOINT.z() / 8.0)) & 7;
  int      iT  = akiLookup [ iX ][ iZ ];
  TScalar  tT  = (TScalar) iT;

  if (iT & 1)
  {
    tValue = tWood.wood (tZ, tY + tT / 3, tX, 15 + tT/2, 1);
  }
  else
  {
    tValue = tWood.wood (tX, tY + tT / 3, tZ, 15 + tT/2, 1);
  }

  tValue = clamp (tValue, 0, 1);

  tRet = lerp (tColor, tBaseColor, tValue);
  
  srand (iT << 2);

  tRet *= 1.0 - frand() * 0.4;
  
  return tRet;

}  /* evaluate() */
Пример #3
0
void PlaneViewer::draw(TVectorImageP vi) {
  TRectD bbox(vi->getBBox());
  TRect bboxI(tfloor(bbox.x0), tfloor(bbox.y0), tceil(bbox.x1) - 1,
              tceil(bbox.y1) - 1);

  TVectorRenderData rd(TAffine(), bboxI, vi->getPalette(), 0, true, true);
  tglDraw(rd, vi.getPointer());
}
Пример #4
0
bool TCacheResource::checkTile(const TTile &tile) const
{
	//Ensure that tile has integer geoometry.
	TPointD tileFracPos(tile.m_pos.x - tfloor(tile.m_pos.x), tile.m_pos.y - tfloor(tile.m_pos.y));
	if (tileFracPos.x != 0.0 || tileFracPos.y != 0.0) {
		assert(!"The passed tile must have integer geometry!");
		return false;
	}

	return true;
}
Пример #5
0
void TRop::over(const TRasterP &out, const TRasterP &up, const TPoint &pos, const TAffine &aff,
				ResampleFilterType filterType)
{
	if (aff.isIdentity())
		//simple over with offset
		TRop::over(out, up, pos);
	else {
		TRect rasterBounds = up->getBounds();
		TRectD dbounds(rasterBounds.x0, rasterBounds.y0, rasterBounds.x1, rasterBounds.y1);
		dbounds = aff * dbounds;
		TRect bounds(tfloor(dbounds.x0), tfloor(dbounds.y0), tceil(dbounds.x1), tceil(dbounds.y1));
		TRasterP tmp = up->create(bounds.getLx(), bounds.getLy());
		resample(tmp, up, TTranslation(-dbounds.getP00()) * aff, filterType);
		TRop::over(out, tmp, pos);
	}
}
Пример #6
0
TScalar TWood::wood (const TScalar ktX,
                     const TScalar ktY,
                     const TScalar ktZ,
                     const TScalar ktRINGSCALE,
                     const TScalar ktGRAINFACTOR) const
{
  TVector  tQ;
  TScalar  tT;
  TScalar  tR;
  TScalar  tS;

  tT =  ktZ / ktRINGSCALE;
  tQ =  TVector (ktX * 8.0, ktY * 8.0, ktZ);
  tT += tNoise.noise (tQ) / 16.0;

  tQ =  TVector (ktX, tT, ktY + 12.93);
  tR =  ktRINGSCALE * tNoise.noise (tQ);
  tR -= tfloor (tR);
  tR =  0.2 + 0.8 * smoothstep (0.2, 0.55, tR) * (1.0 - smoothstep (0.75, 0.8, tR));
  
  tQ =  TVector (ktX * 128.0 + 5.0, ktZ * 8.0 - 3.0, ktY * 128.0 + 1);
  tS =  ktGRAINFACTOR * (1.3 - tNoise.noise (tQ)) + (1.0 - ktGRAINFACTOR);
  
  return tR * tS * tS;

}  /* wood */
Пример #7
0
//! Adapts image viewer's affine to display the passed viewer rect at maximized
//! ratio
void ImageViewer::adaptView(const QRect &geomRect) {
  if (!m_image) return;

  // Retrieve the rect in image reference and call the associated adaptView
  TRect imgBounds(getImageBounds(m_image));
  TRectD imgBoundsD(imgBounds.x0, imgBounds.y0, imgBounds.x1 + 1,
                    imgBounds.y1 + 1);

  TRectD geomRectD(geomRect.left(), geomRect.top(), geomRect.right() + 1,
                   geomRect.bottom() + 1);
  TRectD viewRectD(getImgToWidgetAffine().inv() * geomRectD);
  TRect viewRect(tfloor(viewRectD.x0), tfloor(viewRectD.y0),
                 tceil(viewRectD.x1) - 1, tceil(viewRectD.y1) - 1);

  adaptView(imgBounds, viewRect);
}
Пример #8
0
Файл: ve.c Проект: EdKeith/core
static D jtremdd(J jt,D a,D b){D q,x,y;
 if(!a)R b;
 ASSERT(!INF(b),EVNAN);
 if(a==inf )R 0<=b?b:a;
 if(a==infm)R 0>=b?b:a;
 q=b/a; x=tfloor(q); y=tceil(q); R teq(x,y)?0:b-a*x;
}
Пример #9
0
	void onDeliver()
	{
		if (m_error) {
			m_error = false;
			MsgBox(DVGui::CRITICAL, QObject::tr("There was an error saving frames for the %1 level.").arg(QString::fromStdWString(m_fp.withoutParentDir().getWideString())));
		}

		bool isPreview = (m_fp.getType() == "noext");

		TImageCache::instance()->remove(toString(m_fp.getWideString() + L".0"));
		TNotifier::instance()->notify(TSceneNameChange());

		if (Preferences::instance()->isGeneratedMovieViewEnabled()) {
			if (!isPreview && (Preferences::instance()->isDefaultViewerEnabled()) &&
				(m_fp.getType() == "mov" || m_fp.getType() == "avi" || m_fp.getType() == "3gp")) {
				QString name = QString::fromStdString(m_fp.getName());
				int index;
				if ((index = name.indexOf("#RENDERID")) != -1) //!quite ugly I know....
					m_fp = m_fp.withName(name.left(index).toStdWString());

				if (!TSystem::showDocument(m_fp)) {
					QString msg(QObject::tr("It is not possible to display the file %1: no player associated with its format").arg(QString::fromStdWString(m_fp.withoutParentDir().getWideString())));
					MsgBox(WARNING, msg);
				}

			}

			else {
				int r0, r1, step;
				TApp *app = TApp::instance();
				ToonzScene *scene = app->getCurrentScene()->getScene();
				TOutputProperties &outputSettings = isPreview ? *scene->getProperties()->getPreviewProperties() : *scene->getProperties()->getOutputProperties();
				outputSettings.getRange(r0, r1, step);
				const TRenderSettings rs = outputSettings.getRenderSettings();
				if (r0 == 0 && r1 == -1)
					r0 = 0, r1 = scene->getFrameCount() - 1;

				double timeStretchFactor = isPreview ? 1.0 : (double)outputSettings.getRenderSettings().m_timeStretchTo /
																 outputSettings.getRenderSettings().m_timeStretchFrom;

				r0 = tfloor(r0 * timeStretchFactor);
				r1 = tceil((r1 + 1) * timeStretchFactor) - 1;

				TXsheet::SoundProperties *prop = new TXsheet::SoundProperties();
				prop->m_frameRate = outputSettings.getFrameRate();
				TSoundTrack *snd = app->getCurrentXsheet()->getXsheet()->makeSound(prop);
				if (outputSettings.getRenderSettings().m_stereoscopic) {
					assert(!isPreview);
					::viewFile(m_fp.withName(m_fp.getName() + "_l"), r0 + 1, r1 + 1, step, isPreview ? rs.m_shrinkX : 1, snd, 0, false, true);
					::viewFile(m_fp.withName(m_fp.getName() + "_r"), r0 + 1, r1 + 1, step, isPreview ? rs.m_shrinkX : 1, snd, 0, false, true);
				} else
					::viewFile(m_fp, r0 + 1, r1 + 1, step, isPreview ? rs.m_shrinkX : 1, snd, 0, false, true);
			}
		}
	}
Пример #10
0
void TRop::fracmove(TRasterP rout, TRasterCM32P rin, const TPaletteP &palette, double dx, double dy)
{
	double w[4] = {1, 0, 0, 0};
	double sum = 0;

	int idx = tfloor(dx);
	int idy = tfloor(dy);
	double fracX = dx - idx;
	double fracY = dy - idy;

	int i, j;
	for (i = 0; i < 2; ++i)
		for (j = 0; j < 2; ++j)
			sum += w[j + 2 * i] = fabs(fracX - j) * fabs(fracY - i);

	for (i = 0; i < 4; ++i)
		w[i] /= sum;

	TRop::convolve_i(rout, rin, idx, idy, w, 2);
}
Пример #11
0
void TRop::fracmove(TRasterP rout, TRasterP rin, double dx, double dy)
{
	//Using a bilinear filter is best - consider that only 4 pixels should contribute
	//to a fractionarily shifted one, with weights proportional to the intersection areas.
	double w[4] = {1, 0, 0, 0};
	double sum = 0;

	int idx = tfloor(dx);
	int idy = tfloor(dy);
	double fracX = dx - idx;
	double fracY = dy - idy;

	int i, j;
	for (i = 0; i < 2; ++i)
		for (j = 0; j < 2; ++j)
			sum += w[j + 2 * i] = fabs(fracX - j) * fabs(fracY - i);

	for (i = 0; i < 4; ++i)
		w[i] /= sum;

	TRop::convolve_i(rout, rin, idx, idy, w, 2);
}
Пример #12
0
void TRop::over(const TRasterP &out,
				const TRasterP &up,
				const TAffine &aff,
				ResampleFilterType filterType)
{
	out->lock();
	up->lock();

	if (filterType == ClosestPixel || filterType == Bilinear)
		::quickPut(out, up, aff, filterType);
	else {
		TRect rasterBounds = up->getBounds();
		TRectD dbounds(rasterBounds.x0, rasterBounds.y0, rasterBounds.x1 + 1, rasterBounds.y1 + 1);
		dbounds = aff * dbounds;
		TRect bounds(tfloor(dbounds.x0), tfloor(dbounds.y0), tceil(dbounds.x1) - 1, tceil(dbounds.y1) - 1);
		TRasterP tmp = up->create(bounds.getLx(), bounds.getLy());
		resample(tmp, up, TTranslation(-bounds.x0, -bounds.y0) * aff, filterType);
		over(out, tmp, bounds.getP00());
	}
	out->unlock();
	up->unlock();
}
Пример #13
0
void PlaneViewer::drawBackground() {
  glClearColor(m_bgColorF[0], m_bgColorF[1], m_bgColorF[2], 1.0);
  glClear(GL_COLOR_BUFFER_BIT);

  if (m_bgColorF[0] != m_bgColorF[3] || m_bgColorF[1] != m_bgColorF[4] ||
      m_bgColorF[2] != m_bgColorF[5]) {
    // Cast the widget rect to world rect
    TRectD rect(winToWorld(0, 0), winToWorld(width(), height()));

    // Deduce chess geometry
    TRect chessRect(tfloor(rect.x0 / m_chessSize),
                    tfloor(rect.y0 / m_chessSize), tceil(rect.x1 / m_chessSize),
                    tceil(rect.y1 / m_chessSize));

    // Draw chess squares
    glColor3f(m_bgColorF[3], m_bgColorF[4], m_bgColorF[5]);
    glBegin(GL_QUADS);

    int x, y;
    TPointD pos;
    double chessSize2 = 2.0 * m_chessSize;

    for (y = chessRect.y0; y < chessRect.y1; ++y) {
      pos.y = y * m_chessSize;
      for (x = chessRect.x0 + ((chessRect.x0 + y) % 2), pos.x = x * m_chessSize;
           x < chessRect.x1; x += 2, pos.x += chessSize2) {
        glVertex2d(pos.x, pos.y);
        glVertex2d(pos.x + m_chessSize, pos.y);
        glVertex2d(pos.x + m_chessSize, pos.y + m_chessSize);
        glVertex2d(pos.x, pos.y + m_chessSize);
      }
    }

    glEnd();
  }
}
Пример #14
0
TRect TRasterImageUtils::convertWorldToRaster(const TRectD &area, const TRasterImageP ri)
{
	if (area.isEmpty())
		return TRect();
	if (!ri || !ri->getRaster())
		return TRect(tfloor(area.x0), tfloor(area.y0), tfloor(area.x1) - 1, tfloor(area.y1) - 1);
	TRasterP ras = ri->getRaster();
	TRectD rect(area + ras->getCenterD());
	return TRect(tfloor(rect.x0), tfloor(rect.y0), tceil(rect.x1) - 1, tceil(rect.y1) - 1);
}
Пример #15
0
inline std::string TCacheResource::getCellCacheId(const TPoint &cellPos) const
{
	return getCellCacheId(tfloor(cellPos.x / (double)latticeStep),
						  tfloor(cellPos.y / (double)latticeStep));
}
Пример #16
0
	void doCompute(TTile &tile, double frame, const TRenderSettings &info)
	{
		bool isWarped = m_warped.isConnected();

		if (!isWarped)
			return;

		if (fabs(m_intensity->getValue(frame)) < 0.01) {
			m_warped->compute(tile, frame, info);
			return;
		}

		int shrink = (info.m_shrinkX + info.m_shrinkY) / 2;
		double scale = sqrt(fabs(info.m_affine.det()));
		double gridStep = 1.5 * m_gridStep->getValue(frame);

		WarpParams params;
		params.m_intensity = m_intensity->getValue(frame) / gridStep;
		params.m_warperScale = scale * gridStep;
		params.m_sharpen = m_sharpen->getValue();
		params.m_shrink = shrink;
		double evolution = m_evol->getValue(frame);
		double size = 100.0 / info.m_shrinkX;
		TPointD pos(m_posx->getValue(frame), m_posy->getValue(frame));

		//The warper is calculated on a standard reference, with fixed dpi. This makes sure
		//that the lattice created for the warp does not depend on camera transforms and resolution.
		TRenderSettings warperInfo(info);
		double warperScaleFactor = 1.0 / params.m_warperScale;
		warperInfo.m_affine = TScale(warperScaleFactor) * info.m_affine;

		//Retrieve tile's geometry
		TRectD tileRect;
		{
			TRasterP tileRas = tile.getRaster();
			tileRect = TRectD(tile.m_pos, TDimensionD(tileRas->getLx(), tileRas->getLy()));
		}

		//Build the compute rect
		TRectD warpedBox, warpedComputeRect, tileComputeRect;
		m_warped->getBBox(frame, warpedBox, info);

		getWarpComputeRects(tileComputeRect, warpedComputeRect, warpedBox, tileRect, params);

		if (tileComputeRect.getLx() <= 0 || tileComputeRect.getLy() <= 0)
			return;
		if (warpedComputeRect.getLx() <= 0 || warpedComputeRect.getLy() <= 0)
			return;

		TRectD warperComputeRect(TScale(warperScaleFactor) * tileComputeRect);
		double warperEnlargement = getWarperEnlargement(params);
		warperComputeRect = warperComputeRect.enlarge(warperEnlargement);
		warperComputeRect.x0 = tfloor(warperComputeRect.x0);
		warperComputeRect.y0 = tfloor(warperComputeRect.y0);
		warperComputeRect.x1 = tceil(warperComputeRect.x1);
		warperComputeRect.y1 = tceil(warperComputeRect.y1);

		//Compute the warped tile
		TTile tileIn;
		m_warped->allocateAndCompute(tileIn, warpedComputeRect.getP00(),
									 TDimension(warpedComputeRect.getLx(), warpedComputeRect.getLy()),
									 tile.getRaster(), frame, info);
		TRasterP rasIn = tileIn.getRaster();

		//Compute the warper tile
		TSpectrum::ColorKey colors[] = {
			TSpectrum::ColorKey(0, TPixel32::White),
			TSpectrum::ColorKey(1, TPixel32::Black)};

		TSpectrumParamP cloudscolors = TSpectrumParamP(tArrayCount(colors), colors);

		//Build the warper
		warperInfo.m_affine = warperInfo.m_affine;
		TAffine aff = warperInfo.m_affine.inv();

		TTile warperTile;
		TRasterP rasWarper = rasIn->create(warperComputeRect.getLx(), warperComputeRect.getLy());
		warperTile.m_pos = warperComputeRect.getP00();
		warperTile.setRaster(rasWarper);

		{
			TRenderSettings info2(warperInfo);

			//Now, separate the part of the affine the Fx can handle from the rest.
			TAffine fxHandledAffine = handledAffine(warperInfo, frame);
			info2.m_affine = fxHandledAffine;

			TAffine aff = warperInfo.m_affine * fxHandledAffine.inv();
			aff.a13 /= warperInfo.m_shrinkX;
			aff.a23 /= warperInfo.m_shrinkY;

			TRectD rectIn = aff.inv() * warperComputeRect;

			//rectIn = rectIn.enlarge(getResampleFilterRadius(info));  //Needed to counter the resample filter

			TRect rectInI(tfloor(rectIn.x0), tfloor(rectIn.y0), tceil(rectIn.x1) - 1, tceil(rectIn.y1) - 1);

			// rasIn e' un raster dello stesso tipo di tile.getRaster()

			TTile auxtile(warperTile.getRaster()->create(rectInI.getLx(), rectInI.getLy()), convert(rectInI.getP00()));

			TPointD mypos(auxtile.m_pos - pos);

			double scale2 = sqrt(fabs(info2.m_affine.det()));
			doClouds(auxtile.getRaster(), cloudscolors, mypos, evolution, size, 0.0, 1.0, PNOISE_CLOUDS, scale2, frame);

			info2.m_affine = aff;
			TRasterFx::applyAffine(warperTile, auxtile, info2);
		}

		//Warp
		TPointD db;
		TRect rasComputeRectI(convert(tileComputeRect - tileRect.getP00(), db));
		TRasterP tileRas = tile.getRaster()->extract(rasComputeRectI);

		TPointD rasInPos(warpedComputeRect.getP00() - tileComputeRect.getP00());
		TPointD warperPos((TScale(params.m_warperScale) * warperComputeRect.getP00()) - tileComputeRect.getP00());
		warp(tileRas, rasIn, rasWarper, rasInPos, warperPos, params);
	}
Пример #17
0
  void doCompute(TTile &tile, double frame,
                 const TRenderSettings &info) override {
    bool isWarped = m_warped.isConnected();

    if (!isWarped) return;

    if (fabs(m_intensity->getValue(frame)) < 0.01) {
      m_warped->compute(tile, frame, info);
      return;
    }

    int shrink      = (info.m_shrinkX + info.m_shrinkY) / 2;
    double scale    = sqrt(fabs(info.m_affine.det()));
    double gridStep = 1.5 * m_gridStep->getValue(frame);

    WarpParams params;
    params.m_intensity   = m_intensity->getValue(frame) / gridStep;
    params.m_warperScale = scale * gridStep;
    params.m_sharpen     = m_sharpen->getValue();
    params.m_shrink      = shrink;
    double period        = m_period->getValue(frame) / info.m_shrinkX;
    double count         = m_count->getValue(frame);
    double cycle         = m_cycle->getValue(frame) / info.m_shrinkX;
    double scaleX        = m_scaleX->getValue(frame) / 100.0;
    double scaleY        = m_scaleY->getValue(frame) / 100.0;
    double angle         = -m_angle->getValue(frame);
    TPointD center       = m_center->getValue(frame) * (1.0 / info.m_shrinkX);

    // The warper is calculated on a standard reference, with fixed dpi. This
    // makes sure
    // that the lattice created for the warp does not depend on camera
    // transforms and resolution.
    TRenderSettings warperInfo(info);
    double warperScaleFactor = 1.0 / params.m_warperScale;
    warperInfo.m_affine      = TScale(warperScaleFactor) * info.m_affine;

    // Retrieve tile's geometry
    TRectD tileRect;
    {
      TRasterP tileRas = tile.getRaster();
      tileRect =
          TRectD(tile.m_pos, TDimensionD(tileRas->getLx(), tileRas->getLy()));
    }

    // Build the compute rect
    TRectD warpedBox, warpedComputeRect, tileComputeRect;
    m_warped->getBBox(frame, warpedBox, info);

    getWarpComputeRects(tileComputeRect, warpedComputeRect, warpedBox, tileRect,
                        params);

    if (tileComputeRect.getLx() <= 0 || tileComputeRect.getLy() <= 0) return;
    if (warpedComputeRect.getLx() <= 0 || warpedComputeRect.getLy() <= 0)
      return;

    TRectD warperComputeRect(TScale(warperScaleFactor) * tileComputeRect);
    double warperEnlargement = getWarperEnlargement(params);
    warperComputeRect        = warperComputeRect.enlarge(warperEnlargement);
    warperComputeRect.x0     = tfloor(warperComputeRect.x0);
    warperComputeRect.y0     = tfloor(warperComputeRect.y0);
    warperComputeRect.x1     = tceil(warperComputeRect.x1);
    warperComputeRect.y1     = tceil(warperComputeRect.y1);

    // Compute the warped tile
    TTile tileIn;
    m_warped->allocateAndCompute(
        tileIn, warpedComputeRect.getP00(),
        TDimension(warpedComputeRect.getLx(), warpedComputeRect.getLy()),
        tile.getRaster(), frame, info);
    TRasterP rasIn = tileIn.getRaster();

    // Compute the warper tile
    TSpectrum::ColorKey colors[] = {TSpectrum::ColorKey(0, TPixel32::White),
                                    TSpectrum::ColorKey(0.5, TPixel32::Black),
                                    TSpectrum::ColorKey(1, TPixel32::White)};

    TSpectrumParamP ripplecolors = TSpectrumParamP(tArrayCount(colors), colors);

    // Build the multiradial
    warperInfo.m_affine = warperInfo.m_affine * TTranslation(center) *
                          TRotation(angle) * TScale(scaleX, scaleY);
    TAffine aff      = warperInfo.m_affine.inv();
    TPointD posTrasf = aff * (warperComputeRect.getP00());
    TRasterP rasWarper =
        rasIn->create(warperComputeRect.getLx(), warperComputeRect.getLy());
    multiRadial(rasWarper, posTrasf, ripplecolors, period, count, cycle, aff,
                frame);
    // TImageWriter::save(TFilePath("C:\\ripple.tif"), rasWarper);

    // Warp
    TPointD db;
    TRect rasComputeRectI(convert(tileComputeRect - tileRect.getP00(), db));
    TRasterP tileRas = tile.getRaster()->extract(rasComputeRectI);

    TPointD rasInPos(warpedComputeRect.getP00() - tileComputeRect.getP00());
    TPointD warperPos(
        (TScale(params.m_warperScale) * warperComputeRect.getP00()) -
        tileComputeRect.getP00());
    warp(tileRas, rasIn, rasWarper, rasInPos, warperPos, params);
  }
Пример #18
0
inline TCacheResource::PointLess TCacheResource::getCellIndex(const TPoint &pos) const
{
	return PointLess(
		tfloor(pos.x / (double)latticeStep),
		tfloor(pos.y / (double)latticeStep));
}
Пример #19
0
bool RenderCommand::init(bool isPreview)
{
	ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
	TSceneProperties *sprop = scene->getProperties();
	/*-- Preview/Renderに応じてそれぞれのSettingを取得 --*/
	TOutputProperties &outputSettings = isPreview ? *sprop->getPreviewProperties() : *sprop->getOutputProperties();
	outputSettings.getRange(m_r0, m_r1, m_step);
	/*-- シーン全体のレンダリングの場合、m_r1をScene長に設定 --*/
	if (m_r0 == 0 && m_r1 == -1) {
		m_r0 = 0;
		m_r1 = scene->getFrameCount() - 1;
	}
	if (m_r0 < 0)
		m_r0 = 0;
	if (m_r1 >= scene->getFrameCount())
		m_r1 = scene->getFrameCount() - 1;
	if (m_r1 < m_r0) {
		MsgBox(WARNING, QObject::tr("The command cannot be executed because the scene is empty."));
		return false;
		// throw TException("empty scene");
		// non so perche', ma termina il programma
		// nonostante il try all'inizio
	}

	// Initialize the preview case

	/*TRenderSettings rs = sprop->getPreviewProperties()->getRenderSettings();
  TRenderSettings rso = sprop->getOutputProperties()->getRenderSettings();
  rs.m_stereoscopic=true;
  rs.m_stereoscopicShift=0.05;
  rso.m_stereoscopic=true;
  rso.m_stereoscopicShift=0.05;
  sprop->getPreviewProperties()->setRenderSettings(rs);
  sprop->getOutputProperties()->setRenderSettings(rso);*/

	if (isPreview) {
		/*-- PreviewではTimeStretchを考慮しないので、そのままフレーム値を格納してゆく --*/
		m_numFrames = (int)(m_r1 - m_r0 + 1);
		m_r = m_r0;
		m_stepd = m_step;
		m_multimediaRender = 0;
		return true;
	}

	// Full render case

	// Read the output filepath
	TFilePath fp = outputSettings.getPath();
	/*-- ファイル名が指定されていない場合は、シーン名を出力ファイル名にする --*/
	if (fp.getWideName() == L"")
		fp = fp.withName(scene->getScenePath().getName());
	/*-- ラスタ画像の場合、ファイル名にフレーム番号を追加 --*/
	if (TFileType::getInfo(fp) == TFileType::RASTER_IMAGE || fp.getType() == "pct" || fp.getType() == "pic" || fp.getType() == "pict") //pct e' un formato"livello" (ha i settings di quicktime) ma fatto di diversi frames
		fp = fp.withFrame(TFrameId::EMPTY_FRAME);
	fp = scene->decodeFilePath(fp);
	if (!TFileStatus(fp.getParentDir()).doesExist()) {
		try {
			TFilePath parent = fp.getParentDir();
			TSystem::mkDir(parent);
			DvDirModel::instance()->refreshFolder(parent.getParentDir());
		} catch (TException &e) {
			MsgBox(WARNING, QObject::tr("It is not possible to create folder : %1").arg(QString::fromStdString(toString(e.getMessage()))));
			return false;
		} catch (...) {
			MsgBox(WARNING, QObject::tr("It is not possible to create a folder."));
			return false;
		}
	}
	m_fp = fp;

	// Retrieve camera infos
	const TCamera *camera = isPreview ? scene->getCurrentPreviewCamera() : scene->getCurrentCamera();
	TDimension cameraSize = camera->getRes();
	TPointD cameraDpi = camera->getDpi();

	// Retrieve render interval/step/times
	double stretchTo = (double)outputSettings.getRenderSettings().m_timeStretchTo;
	double stretchFrom = (double)outputSettings.getRenderSettings().m_timeStretchFrom;

	m_timeStretchFactor = stretchTo / stretchFrom;
	m_stepd = m_step / m_timeStretchFactor;

	int stretchedR0 = tfloor(m_r0 * m_timeStretchFactor);
	int stretchedR1 = tceil((m_r1 + 1) * m_timeStretchFactor) - 1;

	m_r = stretchedR0 / m_timeStretchFactor;
	m_numFrames = (stretchedR1 - stretchedR0) / m_step + 1;

	// Update the multimedia render switch
	m_multimediaRender = outputSettings.getMultimediaRendering();

	return true;
}
Пример #20
0
void TRop::brush(
	TRaster32P ras,
	const TPoint &aa,
	const TPoint &bb,
	int radius,
	const TPixel32 &col)
{

	TPoint a = aa;
	TPoint b = bb;
	if (a.y > b.y)
		tswap(a, b); //  a e' piu' in basso di b

	int lx = ras->getLx();
	int ly = ras->getLy();
	ras->lock();

	// ----- radius = 0
	if (radius == 0) {
		//  k = +1/-1 se il rettangolo e' inclinato positivamente (0<=m)/negativamente (m<0)
		//  (se k<0 viene fatta una riflessione sulle ascisse prima di tornare alle
		//  coordinate "di schermo")
		int k = 1;
		int dy = b.y - a.y;
		int dx = b.x - a.x;
		if (dx < 0) {
			dx = -dx;
			k = -1;
		}

		assert(dx >= 0);
		assert(dy >= 0);

		double m; //  m sara' definita solo per dx!=0)
		if (dx > 0) {
			m = dy / (double)dx;
		}
		//double length = sqrt(dx*dx + dy*dy);
		const int alpha = dy, beta = -dx;
		const int incE = alpha;
		const int incNE = alpha + beta;
		const int incN = beta;

		//  N.B. le coordinate sono relative ad un sist. di rif. con l'origine in a
		//  l'eq. della retta e' alpha * x + beta * y = 0

		int yMin = tmax(a.y, 0) - a.y;		//  clipping y + cambio  riferimento
		int yMax = tmin(b.y, ly - 1) - a.y; //  (trasporto dell'origine in a)
		if (dx > 0 && m <= 1) {
			//  midpoint algorithm
			TPoint segm;
			if (dy == 0) //  segmento orizzontale: inizializza segm
			{
				segm.x = 0;
				segm.y = yMin;
			} else //  0<m<=1 :  inizializza segm
			{
				segm.x = tceil((yMin - 0.5) / m);
				segm.y = yMin;
			}

			int dSegm = tfloor(alpha * (segm.x + 1) + beta * (segm.y + 0.5));
			while (segm.y <= yMax) {
				int count = 0;					  //  i trati orizzontali di segm vengono disegnati in "blocco"
				while (dSegm < 0 && segm.x <= dx) //  Est:  segm.x<=dx evita il ciclo
				{								  //  infinito quando m=0 (incE=0)
					dSegm = dSegm + incE;
					segm.x++;
					count++;
				}
				//  NordEst
				int xMin, xMax;
				if (k > 0) {
					xMin = tmax(a.x + segm.x - count, a.x, 0); //  clipping x + ritorno alle
					xMax = tmin(a.x + segm.x, b.x, lx - 1);	//  coordinate "di schermo"

				} else {
					xMin = tmax(a.x - segm.x, a.x - dx, 0);			//  clipping x + riflessione + ritorno
					xMax = tmin(a.x - segm.x + count, a.x, lx - 1); //  alle  coordinate "di schermo"
				}

				TPixel32 *p = ras->pixels(segm.y + a.y) + xMin;
				TPixel32 *q = p + (xMax - xMin);

				while (p <= q)
					*p++ = col;

				dSegm = dSegm + incNE;
				segm.x++;
				segm.y++;
			}
		} else //  m>1 oppure segmento verticale
		{
			//  midpoint algorithm
			TPoint segm;
			if (dx == 0) //  segmento verticale: inizializza segm
			{
				segm.x = 0;
				segm.y = yMin;
			} else //  m>1 :  inizializza segm
			{
				segm.x = tround(yMin / m);
				segm.y = yMin;
			}

			int dSegm = tfloor(alpha * (segm.x + 0.5) + beta * (segm.y + 1));
			while (segm.y <= yMax) {
				int xMin, xMax;
				if (k > 0) {
					xMin = tmax(a.x + segm.x, 0);	  //  clipping x + ritorno alle
					xMax = tmin(a.x + segm.x, lx - 1); //  coordinate "di schermo"

				} else {
					xMin = tmax(a.x - segm.x, 0);	  //  clipping x + riflessione + ritorno
					xMax = tmin(a.x - segm.x, lx - 1); //  alle  coordinate "di schermo"
				}

				TPixel32 *p = ras->pixels(segm.y + a.y) + xMin;
				TPixel32 *q = p + (xMax - xMin);

				while (p <= q)
					*p++ = col;

				if (dSegm <= 0) //  NordEst
				{
					dSegm = dSegm + incNE;
					segm.x++;
				} else //  Nord
				{
					dSegm = dSegm + incN;
				}
				segm.y++;
			}
		}
		ras->unlock();
		return;
	}

	HalfCord halfCord(radius);

	int x, y;

	// ----- punti iniziali coincidenti: disegna un cerchio
	if (a == b) {
		int yMin = tmax(a.y - radius, 0);	  //  clipping y
		int yMax = tmin(a.y + radius, ly - 1); //  clipping y
		for (y = yMin; y <= yMax; y++) {
			int deltay = abs(y - a.y);
			int xMin = tmax(a.x - halfCord.getCord(deltay), 0);		 //  clipping x
			int xMax = tmin(a.x + halfCord.getCord(deltay), lx - 1); //  clipping x
			TPixel32 *p = ras->pixels(y) + xMin;
			TPixel32 *q = p + (xMax - xMin);
			while (p <= q)
				*p++ = col;
		}
		ras->unlock();
		return;
	}

	// -----  rettangolo orizzontale (a.y = b.y, a.x != b.x)
	if (a.y == b.y) {
		int yMin = tmax((a.y - radius), 0);		 //  clipping y
		int yMax = tmin((a.y + radius), ly - 1); //  clipping y
		int xLeft = tmin(a.x, b.x);
		int xRight = tmax(a.x, b.x);
		for (y = yMin; y <= yMax; y++) {
			int deltay = abs(y - a.y);
			int xMin = tmax(xLeft - halfCord.getCord(deltay), 0);		//  clipping x
			int xMax = tmin(xRight + halfCord.getCord(deltay), lx - 1); //  clipping x
			TPixel32 *p = ras->pixels(y) + xMin;
			TPixel32 *q = p + (xMax - xMin);
			while (p <= q)
				*p++ = col;
		}
		ras->unlock();
		return;
	}

	// -----  rettangolo verticale (a.x = b.x, a.y != b.y)
	if (a.x == b.x) {

		int xMin = tmax(a.x - radius, 0);	  //  clipping x
		int xMax = tmin(a.x + radius, lx - 1); //  clipping x
		for (x = xMin; x <= xMax; x++) {
			int deltax = abs(x - a.x);
			int yMin = tmax(a.y - halfCord.getCord(deltax), 0);		 //  clipping y
			int yMax = tmin(b.y + halfCord.getCord(deltax), ly - 1); //  clipping y
			if (yMin <= yMax) {
				TPixel32 *p = ras->pixels(yMin) + x;
				TPixel32 *q = ras->pixels(yMax) + x;
				int wrap = ras->getWrap();
				while (p <= q) {
					*p = col;
					p += wrap;
				}
			}
		}
		ras->unlock();
		return;
	}

	// -----  rettangolo inclinato
	//	k = +1/-1 se il rettangolo e' inclinato positivamente/negativamente
	int k = 1;
	int dx = b.x - a.x;
	if (dx < 0) {
		dx = -dx;
		k = -1;
	}
	int dy = b.y - a.y;

	assert(dx > 0);
	assert(dy > 0);

	double length = sqrt((double)(dx * dx + dy * dy));
	const double m = dy / (double)dx;

	//punto di tangenza superiore nel sistema di riferimento del cerchio
	TPointD up(-radius * dy / length, radius * dx / length);

	//semi-ampiezza orizzontale delle "calotte" circolari
	int halfAmplCap = tfloor(-up.x);

	//  A meno di intersezioni relative tra le diverse zone:

	//  le scanline della "calotta" circolare superiore sono (b.y+cutExt,b.y+radius]
	//  le scanline del trapezoide circolare superiore sono [b.y-cutIn,b.y+cutExt]
	//  le scanline del parallelogramma sono (a.y+cutIn,b.y-cutIn)
	//  le scanline del trapezoide circolare inferiore sono [a.y-cutExt,a.y+cutIn]
	//  le scanline della "calotta" circolare inferiore sono [a.y-radius,a.y-cutExt)
	int cutExt, cutIn;

	// vertici del parallelogramma
	TPointD rightUp;
	TPointD rightDown;
	TPointD leftUp;
	TPointD leftDown;
	double mParall; //coeff. angolare parallelogramma

	//  NOTA BENE:  halfAmplCap=0 <=> (radius=0 (caso a parte) , 1)
	if (radius > 1) {
		for (cutExt = radius; cutExt >= 0 && halfCord.getCord(cutExt) <= halfAmplCap; cutExt--)
			;
		cutIn = cutExt; //  vedi else successivo
		rightUp.x = dx + halfCord.getCord(cutIn);
		rightUp.y = dy - cutIn;
		rightDown.x = halfCord.getCord(cutIn);
		rightDown.y = -cutIn;
		leftUp.x = dx - halfCord.getCord(cutIn);
		leftUp.y = dy + cutIn;
		leftDown.x = -halfCord.getCord(cutIn);
		leftDown.y = cutIn;
		mParall = dy / (double)dx;
	} else //  N.B. cutExt != cutIn solo quando radius=1
	{
		cutExt = radius; //  radius=1 => halfAmplCap=0 (non ci sono mai le "calotte" circolari)
		cutIn = 0;		 //  anche per radius=1 il limite "interno" dei trapezoidi circolari e' < radius
		rightUp.x = dx - up.x;
		rightUp.y = dy - up.y;
		rightDown.x = -up.x;
		rightDown.y = -up.y;
		leftUp.x = dx + up.x;
		leftUp.y = dy + up.y;
		leftDown.x = up.x;
		leftDown.y = up.y;
		mParall = m;
	}
	// -----  riempie "calotte" circolari

	// -----  riempie "calotta" circolare inferiore
	int yMin = tmax(a.y - radius, 0);		   //  clipping y
	int yMax = tmin(a.y - cutExt - 1, ly - 1); //  clipping y
	for (y = yMin; y <= yMax; y++) {
		int r = halfCord.getCord(a.y - y);
		int xMin = tmax(a.x - r, 0);	  //  clipping x
		int xMax = tmin(a.x + r, lx - 1); //  clipping x
		TPixel32 *p = ras->pixels(y) + xMin;
		TPixel32 *q = p + (xMax - xMin);
		while (p <= q)
			*p++ = col;
	}
	// -----  riempie "calotta" circolare superiore
	yMin = tmax(b.y + cutExt + 1, 0);  //  clipping y
	yMax = tmin(b.y + radius, ly - 1); //  clipping y
	for (y = yMin; y <= yMax; y++) {
		int r = halfCord.getCord(y - b.y);
		int xMin = tmax(b.x - r, 0);	  //  clipping x
		int xMax = tmin(b.x + r, lx - 1); //  clipping x
		TPixel32 *p = ras->pixels(y) + xMin;
		TPixel32 *q = p + (xMax - xMin);
		while (p <= q)
			*p++ = col;
	}
	// -----  riempie trapezoidi

	// (se k<0 viene fatta una riflessione sulle ascisse prima di tornare alle
	// coordinate "di schermo")

	//  limite destro assoluto delle scanline trapezoide:
	int xSegmMax = tround(dx - up.x); //  coordinata x del punto di tangenza inferiore sul cerchio superiore

	//  limite sinistro assoluto delle scanline:
	int xSegmMin = tround(up.x); //  coordinata x del punto di tangenza superiore sul cerchio inferiore

	// -----  riempie trapezoide inferiore

	// N.B. le coordinate sono relative ad un sist. di rif. con l'origine sul centro
	// del cerchio inferiore

	yMin = tmax(a.y - cutExt, 0) - a.y;						 //  clipping y
	yMax = tmin(a.y + cutIn, b.y - cutIn - 1, ly - 1) - a.y; //  clipping y

	// l'eq. della retta e' alpha * x + beta * y + gammaRight = 0
	const int alpha = dy, beta = -dx;
	const double gammaRight = rightDown.y * dx - rightDown.x * dy;
	const int incE = alpha;
	const int incNE = alpha + beta;
	const int incN = beta;

	if (m <= 1) {
		//  midpoint algorithm; le scanline vengono disegnate solo
		//  sul NordEst. L'ultima scanline non viene disegnata
		TPoint segmRight(tceil((yMin + 0.5 - rightDown.y) / mParall + rightDown.x) - 1, yMin);
		int dSegmRight = tfloor(alpha * (segmRight.x + 1) + beta * (segmRight.y + 0.5) + gammaRight);
		while (segmRight.y <= yMax) {
			if (dSegmRight < 0) //  Est
			{
				dSegmRight = dSegmRight + incE;
				segmRight.x++;
			} else //  NordEst
			{
				int xMin, xMax;
				if (k > 0) {
					xMin = tmax(a.x - halfCord.getCord(abs(segmRight.y)), 0); //  clipping x
					xMax = tmin(a.x + tmin(segmRight.x, xSegmMax), lx - 1);   //  clipping x
				} else {
					xMin = tmax(a.x - tmin(segmRight.x, xSegmMax), 0);			   //  clipping x + ritorno alle
					xMax = tmin(a.x + halfCord.getCord(abs(segmRight.y)), lx - 1); //   coordinate "di schermo"
				}
				TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin;
				TPixel32 *q = p + (xMax - xMin);
				while (p <= q)
					*p++ = col;

				dSegmRight = dSegmRight + incNE;
				segmRight.x++;
				segmRight.y++;
			}
		}
	} else //  m>1
	{
		//  midpoint algorithm; le scanline vengono disegnate sempre
		TPoint segmRight(tround((yMin - rightDown.y) / mParall + rightDown.x), yMin);
		int dSegmRight = tfloor(alpha * (segmRight.x + 0.5) + beta * (segmRight.y + 1) + gammaRight);
		while (segmRight.y <= yMax) {
			int xMin, xMax;
			if (k > 0) {
				xMin = tmax(a.x - halfCord.getCord(abs(segmRight.y)), 0); //  clipping x
				xMax = tmin(a.x + segmRight.x, lx - 1);					  //  clipping x
			} else {
				xMin = tmax(a.x - segmRight.x, 0);							   //  clipping x + ritorno alle coordinate
				xMax = tmin(a.x + halfCord.getCord(abs(segmRight.y)), lx - 1); //  "di schermo"
			}
			TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin;
			TPixel32 *q = p + (xMax - xMin);
			while (p <= q)
				*p++ = col;

			if (dSegmRight <= 0) //  NordEst
			{
				dSegmRight = dSegmRight + incNE;
				segmRight.x++;
			} else //  Nord
			{
				dSegmRight = dSegmRight + incN;
			}
			segmRight.y++;
		}
	}

	// -----  riempie trapezoide superiore

	//  N.B. le coordinate sono relative ad un sist. di rif. con l'origine sul centro
	//  del cerchio superiore
	yMin = tmax(b.y - cutIn, a.y + cutIn + 1, 0) - b.y; //  clipping y
	yMax = tmin(b.y + cutExt, ly - 1) - b.y;			//  clipping y

	//   l'eq. della retta e' alpha * x + beta * y + gammaLeft = 0
	const double gammaLeft = leftDown.y * dx - leftDown.x * dy;

	if (m <= 1) {
		//  midpoint algorithm; le scanline vengono disegnate solo
		//  sul NordEst. L'ultima scanline non viene disegnata
		TPoint segmLeft(tceil((yMin - 0.5 - leftDown.y) / mParall + leftDown.x), yMin);
		int dSegmLeft = tfloor(alpha * (segmLeft.x + 1) + beta * (segmLeft.y + 0.5) + gammaLeft);
		while (segmLeft.y <= yMax) {
			int xMin, xMax;
			if (k > 0) {
				xMin = tmax(b.x + tmax(segmLeft.x, xSegmMin - dx), 0);		  //  clipping x
				xMax = tmin(b.x + halfCord.getCord(abs(segmLeft.y)), lx - 1); //  clipping x
			} else {
				xMin = tmax(b.x - halfCord.getCord(abs(segmLeft.y)), 0);	//  clipping x + ritorno alle
				xMax = tmin(b.x - tmax(segmLeft.x, xSegmMin - dx), lx - 1); //   coordinate "di schermo"
			}
			TPixel32 *p = ras->pixels(segmLeft.y + b.y) + xMin;
			TPixel32 *q = p + (xMax - xMin);

			while (p <= q)
				*p++ = col;
			while (dSegmLeft < 0) {
				dSegmLeft = dSegmLeft + incE;
				segmLeft.x++;
			}
			dSegmLeft = dSegmLeft + incNE;
			segmLeft.x++;
			segmLeft.y++;
		}
	} else //  m>1
	{
		//  midpoint algorithm; le scanline vengono disegnate sempre
		TPoint segmLeft(tround((yMin - leftDown.y) / mParall + leftDown.x), yMin);
		int dSegmLeft = tfloor(alpha * (segmLeft.x + 0.5) + beta * (segmLeft.y + 1) + gammaLeft);
		while (segmLeft.y <= yMax) {
			int xMin, xMax;
			if (k > 0) {
				xMin = tmax(b.x + segmLeft.x, 0);							  //  clipping x
				xMax = tmin(b.x + halfCord.getCord(abs(segmLeft.y)), lx - 1); //  clipping x
			} else {
				xMin = tmax(b.x - halfCord.getCord(abs(segmLeft.y)), 0); //  clipping x + ritorno alle
				xMax = tmin(b.x - segmLeft.x, lx - 1);					 //   coordinate "di schermo"
			}
			TPixel32 *p = ras->pixels(segmLeft.y + b.y) + xMin;
			TPixel32 *q = p + (xMax - xMin);

			while (p <= q)
				*p++ = col;

			if (dSegmLeft <= 0) //  NordEst
			{
				dSegmLeft = dSegmLeft + incNE;
				segmLeft.x++;
			} else //  Nord
			{
				dSegmLeft = dSegmLeft + incN;
			}
			segmLeft.y++;
		}
	}

	// -----  parallelogramma (in alternativa a "parallelogrammoide circolare")

	// N.B. le coordinate sono relative ad un sist. di rif. con l'origine sul centro
	// del cerchio inferiore

	//  retta destra di equaz.   alpha * x + beta * y + gammaRight = 0
	//  retta sinistra di equaz. alpha * x + beta * y + gammaLeft = 0

	yMin = tmax(a.y + cutIn + 1, 0) - a.y;		//clipping y
	yMax = tmin(b.y - cutIn - 1, ly - 1) - a.y; //clipping y
	if (m <= 1) {
		//  midpoint algorithm; le scanline vengono disegnate solo
		//  sul NordEst. L'ultima scanline non viene disegnata
		TPoint segmRight(tceil((yMin + 0.5 - rightDown.y) / mParall + rightDown.x) - 1, yMin);
		TPoint segmLeft = TPoint(tceil((yMin - 0.5 - leftDown.y) / mParall + leftDown.x), yMin);
		int dSegmRight = tfloor(alpha * (segmRight.x + 1) + beta * (segmRight.y + 0.5) + gammaRight);
		int dSegmLeft = tfloor(alpha * (segmLeft.x + 1) + beta * (segmLeft.y + 0.5) + gammaLeft);
		while (segmRight.y <= yMax) {
			if (dSegmRight < 0) //  segmRight a Est
			{
				dSegmRight = dSegmRight + incE;
				segmRight.x++;
			} else //  segmRight a NordEst
			{
				int xMin, xMax;
				if (k > 0) {
					xMin = tmax(a.x + tmax(segmLeft.x, xSegmMin), 0);		//  clipping x
					xMax = tmin(a.x + tmin(segmRight.x, xSegmMax), lx - 1); //  clipping x
				} else {
					xMin = tmax(a.x - tmin(segmRight.x, xSegmMax), 0);	 //  clipping x + ritorno alle
					xMax = tmin(a.x - tmax(segmLeft.x, xSegmMin), lx - 1); //   coordinate "di schermo"
				}

				TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin;
				TPixel32 *q = p + (xMax - xMin);

				while (p <= q)
					*p++ = col;

				dSegmRight = dSegmRight + incNE;
				segmRight.x++;
				segmRight.y++;

				while (dSegmLeft < 0) //  segmLeft a Est
				{
					dSegmLeft = dSegmLeft + incE;
					segmLeft.x++;
				}
				//  segmLeft a NordEst
				dSegmLeft = dSegmLeft + incNE;
				segmLeft.x++;
				segmLeft.y++;
			}
		}
	} else //  m>1
	{
		//  midpoint algorithm; le scanline vengono disegnate sempre
		TPoint segmRight(tround((yMin - rightDown.y) / mParall + rightDown.x), yMin);
		TPoint segmLeft(tround((yMin - leftDown.y) / mParall + leftDown.x), yMin);
		int dSegmRight = tfloor(alpha * (segmRight.x + 0.5) + beta * (segmRight.y + 1) + gammaRight);
		int dSegmLeft = tfloor(alpha * (segmLeft.x + 0.5) + beta * (segmLeft.y + 1) + gammaLeft);
		while (segmRight.y <= yMax) {
			int xMin, xMax;
			if (k > 0) {
				xMin = tmax(a.x + segmLeft.x, 0);		//  clipping x
				xMax = tmin(a.x + segmRight.x, lx - 1); //  clipping x
			} else {
				xMin = tmax(a.x - segmRight.x, 0);	 //  clipping x + ritorno alle
				xMax = tmin(a.x - segmLeft.x, lx - 1); //   coordinate "di schermo"
			}

			TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin;
			TPixel32 *q = p + (xMax - xMin);

			while (p <= q)
				*p++ = col;

			if (dSegmRight <= 0) //  segmRight a NordEst
			{
				dSegmRight = dSegmRight + incNE;
				segmRight.x++;
			} else //  segmRight a Nord
			{
				dSegmRight = dSegmRight + incN;
			}
			segmRight.y++;

			if (dSegmLeft <= 0) //  segmLeft a NordEst
			{
				dSegmLeft = dSegmLeft + incNE;
				segmLeft.x++;
			} else //  segmLeft a Nord
			{
				dSegmLeft = dSegmLeft + incN;
			}
		}
	}

	// ----  parallelogrammoide circolare (in alternativa a parallelogramma)

	// N.B. coordinate di schermo (riflessione per k<0 )

	yMin = tmax(b.y - cutIn, 0);
	yMax = tmin(a.y + cutIn, ly - 1);
	for (y = yMin; y <= yMax; y++) {
		int xMin, xMax;
		if (k > 0) {
			xMin = tmax(a.x - halfCord.getCord(abs(y - a.y)), 0);	  //  clipping x
			xMax = tmin(b.x + halfCord.getCord(abs(b.y - y)), lx - 1); //  clipping x
		} else {
			xMin = tmax(b.x - halfCord.getCord(abs(b.y - y)), 0);	  //  clipping x + ritorno alle
			xMax = tmin(a.x + halfCord.getCord(abs(y - a.y)), lx - 1); //   coordinate "di schermo"
		}
		TPixel32 *p = ras->pixels(y) + xMin;
		TPixel32 *q = p + (xMax - xMin);
		while (p <= q)
			*p++ = col;
	}
	ras->unlock();
}