Пример #1
0
  void dump_grid_range_highlight(const Grid & grid,
				 ssize_t ix0, ssize_t iy0,
				 ssize_t ix1, ssize_t iy1,
				 ssize_t ixhigh, ssize_t iyhigh,
				 FILE * stream)
  {
    PVDEBUG("%zu   %zu   %zu   %zu   %zu   %zu\n",
	    ix0, iy0, ix1, iy1, ixhigh, iyhigh);
    fprintf(stream, " ");
    for(ssize_t ix(ix0); ix <= ix1; ++ix)
      if(ix == ixhigh) fprintf(stream, " ***********");
      else             fprintf(stream, "            ");
    fprintf(stream, " \n");
    ssize_t iy(iy1);
    for(/**/; iy != iy0; --iy){
      const char * high(iy == iyhigh ? "*" : " ");
      linesep(grid, stream, ix0, ix1, 0, " ");
      line1(grid, stream, iy, ix0, ix1, 0, high);
      line2(grid, stream, iy, ix0, ix1, 0, high);
      line3(grid, stream, iy, ix0, ix1, 0, high);
      line4(grid, stream, iy, ix0, ix1, 0, high);
    }
    const char * high(iy == iyhigh ? "*" : " ");
    linesep(grid, stream, ix0, ix1, 0, " ");
    line1(grid, stream, iy, ix0, ix1, 0, high);
    line2(grid, stream, iy, ix0, ix1, 0, high);
    line3(grid, stream, iy, ix0, ix1, 0, high);
    line4(grid, stream, iy, ix0, ix1, 0, high);
    linesep(grid, stream, ix0, ix1, 0, " ");
    fprintf(stream, " ");
    for(ssize_t ix(ix0); ix <= ix1; ++ix)
      if(ix == ixhigh) fprintf(stream, " ***********");
      else             fprintf(stream, "            ");
    fprintf(stream, " \n");
  }
Пример #2
0
  void dump_grid_range(const Grid & grid,
		       ssize_t ix0, ssize_t iy0, ssize_t ix1, ssize_t iy1,
		       FILE * stream)
  {
    PVDEBUG("%zu   %zu   %zu   %zu\n", ix0, iy0, ix1, iy1);
    const char * even("");
    const char * oddsep;
    const char * oddpre;
    if (grid.GetNeighborhood() == Grid::SIX) {
      oddsep = "+-----";
      oddpre = "      ";
    }
    else {
      oddsep = even;
      oddpre = even;
    }
    ssize_t iy(iy1);
    const char * prefix;
    for(/**/; iy != iy0; --iy){
      if(iy % 2){
	linesep(grid, stream, ix0, ix1, oddsep, 0);
	prefix = oddpre;
      }
      else{
	linesep(grid, stream, ix0, ix1, even, 0);
	prefix = even;
      }
      line1(grid, stream, iy, ix0, ix1, prefix, 0);
      line2(grid, stream, iy, ix0, ix1, prefix, 0);
      line3(grid, stream, iy, ix0, ix1, prefix, 0);
      line4(grid, stream, iy, ix0, ix1, prefix, 0);
    }
    if(iy % 2){
      linesep(grid, stream, ix0, ix1, oddsep, 0);
      prefix = oddpre;
    }
    else{
      linesep(grid, stream, ix0, ix1, even, 0);
      prefix = even;
    }
    line1(grid, stream, iy, ix0, ix1, prefix, 0);
    line2(grid, stream, iy, ix0, ix1, prefix, 0);
    line3(grid, stream, iy, ix0, ix1, prefix, 0);
    line4(grid, stream, iy, ix0, ix1, prefix, 0);
    if(iy % 2)
      linesep(grid, stream, ix0, ix1, even, 0);
    else
      linesep(grid, stream, ix0, ix1, oddsep, 0);
  }
Пример #3
0
void tst_QRay3D::contains_ray()
{
    QFETCH(QVector3D, origin);
    QFETCH(QVector3D, direction);
    QFETCH(QVector3D, point);
    QFETCH(bool, contains);

    Qt3DRender::RayCasting::QRay3D line(origin, direction);
    if (contains) {
        Qt3DRender::RayCasting::QRay3D line2(point, direction);
        QVERIFY(line.contains(line2));
        QVERIFY(line2.contains(line));

        // Reversed direction is also contained.
        Qt3DRender::RayCasting::QRay3D line3(point, -direction);
        QVERIFY(line.contains(line2));
        QVERIFY(line2.contains(line));

        // Different direction.
        Qt3DRender::RayCasting::QRay3D line4(point, QVector3D(direction.y(), direction.x(), direction.z()));
        QVERIFY(!line.contains(line4));
        QVERIFY(!line4.contains(line));
    } else {
        Qt3DRender::RayCasting::QRay3D line2(point, direction);
        QVERIFY(!line.contains(line2));
        QVERIFY(!line2.contains(line));
    }
}
Пример #4
0
void Rectangle::draw(Frame* fr) {
    /* 
     * x1y2-------x2y2
     * |             |
     * |             |
     * |             |
     * x1y1-------x2y1
     */
    if(x1 > x2 && y1 > y2) {
        std::swap(x1, x2);
        std::swap(y1, y2);
    }
    if(is_valid(fr)) {
        // Create 4 lines
        Line line1(x1, y1, x1, y2);
        Line line2(x1, y2, x2, y2);
        Line line3(x2, y2, x2, y1);
        Line line4(x2, y1, x1, y1);
        // Draw them
        line1.draw(fr);
        line2.draw(fr);
        line3.draw(fr);
        line4.draw(fr);
    } else {
        throw std::runtime_error("Rechteck nicht korrekt!");
    }
}
Пример #5
0
void test_circuit_rc()
{
	ngdc dc("dc1", 5);
	ngresistor r("r1", 5);
	ngcapacitor c("c1", 0.2);
	ngground gnd;

	ngline line1(dc[0], r[0]);
	ngline line2(r[1], c[0]);
	ngline line3(c[1], dc[1]);
	ngline line4(dc[0], gnd[0]);

	schema sch("design1");
	sch.AddDevice(&dc);
	sch.AddDevice(&r);
	sch.AddDevice(&c);
	sch.AddDevice(&gnd);

	sch.AddLine(&line1);
	sch.AddLine(&line2);
	sch.AddLine(&line3);
	sch.AddLine(&line4);

	circuit cir(&sch);
	cir.Tran("1s");
	
	do 
	{
		Sleep(200);
	} while (cir.IsRunning());
}
Пример #6
0
vector<Pixel> Rectangle::getPixels() const{

	Point p1(mPositionX,mPositionY);
	Point p2(mPositionX+mWidth,mPositionY);
	Point p3(mPositionX,mPositionY+mHeight);
	Point p4(mPositionX+mWidth,mPositionY+mHeight);

	Line line1(p1,p2,mColor);
	Line line2(p2,p4,mColor);
	Line line3(p3,p4,mColor);
	Line line4(p1,p3,mColor);

	vector<Pixel> linePixels1 = line1.getPixels();
	vector<Pixel> linePixels2 = line2.getPixels();
	vector<Pixel> linePixels3 = line3.getPixels();
	vector<Pixel> linePixels4 = line4.getPixels();

	vector<Pixel> pixels;

	pixels.insert(pixels.end(),linePixels1.begin(),linePixels1.end());
	pixels.insert(pixels.end(),linePixels2.begin(),linePixels2.end());
	pixels.insert(pixels.end(),linePixels3.begin(),linePixels3.end());
	pixels.insert(pixels.end(),linePixels4.begin(),linePixels4.end());

	return pixels;
}
Пример #7
0
std::string Diagnostics::GetFrameOverlayString(const GPUStats& aStats) {
  TimeStamp now = TimeStamp::Now();
  unsigned fps = unsigned(mCompositeFps.AddFrameAndGetFps(now));
  unsigned txnFps = unsigned(mTransactionFps.GetFPS(now));

  float pixelFillRatio =
      aStats.mInvalidPixels
          ? float(aStats.mPixelsFilled) / float(aStats.mInvalidPixels)
          : 0.0f;
  float screenFillRatio = aStats.mScreenPixels ? float(aStats.mPixelsFilled) /
                                                     float(aStats.mScreenPixels)
                                               : 0.0f;

  if (aStats.mDrawTime) {
    mGPUDrawMs.Add(aStats.mDrawTime.value());
  }

  std::string gpuTimeString;
  if (mGPUDrawMs.Empty()) {
    gpuTimeString = "N/A";
  } else {
    gpuTimeString = nsPrintfCString("%0.1fms", mGPUDrawMs.Average()).get();
  }

  // DL  = nsDisplayListBuilder
  // FLB = FrameLayerBuilder
  // R   = ClientLayerManager::EndTransaction
  // CP  = ShadowLayerForwarder::EndTransaction (txn build)
  // TX  = LayerTransactionChild::SendUpdate (IPDL serialize+send)
  // UP  = LayerTransactionParent::RecvUpdate (IPDL deserialize, update, APZ
  //                                           update)
  // CC_BUILD = Container prepare/composite frame building
  // CC_EXEC  = Container render/composite drawing
  nsPrintfCString line1("FPS: %d (TXN: %d)", fps, txnFps);
  nsPrintfCString line2(
      "[CC] Build: %0.1fms Exec: %0.1fms GPU: %s Fill Ratio: %0.1f/%0.1f",
      mPrepareMs.Average(), mCompositeMs.Average(), gpuTimeString.c_str(),
      pixelFillRatio, screenFillRatio);
  nsCString line3;
  if (mDlb2Ms.Average() != 0.0f) {
    line3 += nsPrintfCString(
        "[Content] DL: %0.1f/%0.1fms FLB: %0.1fms Raster: %0.1fms",
        mDlb2Ms.Average(), mDlbMs.Average(), mFlbMs.Average(),
        mRasterMs.Average());
  } else {
    line3 += nsPrintfCString(
        "[Content] DL: %0.1fms FLB: %0.1fms Raster: %0.1fms", mDlbMs.Average(),
        mFlbMs.Average(), mRasterMs.Average());
  }
  nsPrintfCString line4("[IPDL] Build: %0.1fms Send: %0.1fms Update: %0.1fms",
                        mSerializeMs.Average(), mSendMs.Average(),
                        mUpdateMs.Average());

  return std::string(line1.get()) + "\n" + std::string(line2.get()) + "\n" +
         std::string(line3.get()) + "\n" + std::string(line4.get());
}
Пример #8
0
TEST(CsvWriter, TestWriteLine) {

  // Write a bunch of lines to a csv file.
  CsvWriter csv_writer(csv_write_file);
  EXPECT_TRUE(csv_writer.IsOpen());

  std::vector<int> line1 = {1, 2, 3, 4, 5};
  std::vector<double> line2 = {6.0, 7.0, 8.0, 9.0, 10.0};
  std::vector<std::string> line3 = {"a", "b", "c", "d", "e"};
  Eigen::Matrix<double, 5, 1> line4;
  line4 << 11.0, 12.0, 13.0, 14.0, 15.0;

  EXPECT_TRUE(csv_writer.WriteLine(line1));
  EXPECT_TRUE(csv_writer.WriteLine(line2));
  EXPECT_TRUE(csv_writer.WriteLine(line3));
  EXPECT_TRUE(csv_writer.WriteLine(line4));
  EXPECT_TRUE(csv_writer.Close());

  // Read back the lines from the csv file.
  CsvReader csv_reader(csv_write_file);
  EXPECT_TRUE(csv_reader.IsOpen());
  EXPECT_TRUE(csv_reader.HasMoreLines());

  // First line.
  std::vector<std::string> tokenized_line;
  EXPECT_TRUE(csv_reader.ReadLine(&tokenized_line));
  EXPECT_EQ(line1.size(), tokenized_line.size());
  for (size_t ii = 0; ii < tokenized_line.size(); ++ii) {
    EXPECT_EQ(line1[ii], std::stoi(tokenized_line[ii]));
  }

  // Second line.
  EXPECT_TRUE(csv_reader.ReadLine(&tokenized_line));
  EXPECT_EQ(line2.size(), tokenized_line.size());
  for (size_t ii = 0; ii < tokenized_line.size(); ++ii) {
    EXPECT_EQ(line2[ii], std::stod(tokenized_line[ii]));
  }

  // Third line.
  EXPECT_TRUE(csv_reader.ReadLine(&tokenized_line));
  EXPECT_EQ(line3.size(), tokenized_line.size());
  for (size_t ii = 0; ii < tokenized_line.size(); ++ii) {
    EXPECT_EQ(line3[ii], tokenized_line[ii].c_str());
  }

  // Fourth line.
  EXPECT_TRUE(csv_reader.ReadLine(&tokenized_line));
  EXPECT_EQ(line4.size(), tokenized_line.size());
  for (size_t ii = 0; ii < tokenized_line.size(); ++ii) {
    EXPECT_EQ(line4(ii), std::stod(tokenized_line[ii]));
  }

  // Delete the file.
  std::remove(csv_write_file.c_str());
}
Пример #9
0
main(){
  data_init();
  line1(1,1,17,13);
  data_print();

  data_init();
  line3(1,1,17,11);
  line3(1,4,7,18);
  data_print();

  data_init();
  line4(7,5,5,1);
  line4(5,5,1,3);
  line4(18,1,2,11);
  line4(18,4,6,18);
  data_print();

  data_init();
  line5(5,5,18,9, 3);
  line5(10,18,3,9, 4);
  data_print();

  data_init();
  circ2(12,12,3);
  circ2(10,10,9);
  data_print();

  data_init();
  circ3(11,10,3, 1,1);
  circ3(10,10,9, 3,0);
  data_print();

  data_init();
  circ3(10,10,8, 8,0);
  data_print();

  return 0;
}
Пример #10
0
void test_circuit_rc_tran()
{
	ngdc dc("dc1", 5);
	ngspdt spdt("spdt");
	ngresistor r("r1", 5);
	ngcapacitor c("c1", 0.2);
	ngground gnd;

	ngline line1(dc.pos, spdt.throw1);
	ngline line2(spdt.pole, r.p1);
	ngline line3(r.p2, c.p1);
	ngline line4(c.p2, dc.neg);
	ngline line5(spdt.throw2, gnd.ground);
	ngline line0(dc.neg, gnd.ground);

	schema sch;
	sch.AddDevices(&dc, &spdt, &r, &c, &gnd, 0);
	sch.AddLines(&line1, &line2, &line3, &line4, &line5, &line0, 0);


	circuit cir(&sch);
	cir.Tran("1t", "100u");

	do 
	{
		Sleep(200);
		char ch = getchar();
		switch (ch)
		{
		case 'a':
			// switchover to charge or discharge
			cir.SwitchOver(&spdt);
			Sleep(200);
			break;
		case 'q':
			cir.Halt();
		default:
			break;
		};
	} while (cir.IsRunning());

	cir.Do("plot all");
}
Пример #11
0
bool Line::visit_collides(const Rect *rect) const
{
	Line line1(rect->get_x(), rect->get_y(),
	           rect->get_x() + rect->get_w() - 1,
	           rect->get_y());
	Line line2(rect->get_x(), rect->get_y(),
	           rect->get_x(),
	           rect->get_y() + rect->get_h() - 1);
	Line line3(rect->get_x() + rect->get_w() - 1,
	           rect->get_y(),
	           rect->get_x() + rect->get_w() - 1,
	           rect->get_y() + rect->get_h() - 1);
	Line line4(rect->get_x(),
	           rect->get_y() + rect->get_h() - 1,
	           rect->get_x() + rect->get_w() - 1,
	           rect->get_y() + rect->get_h() - 1);
	return rect->contains(m_x1, m_y1) ||
		rect->contains(m_x2, m_y2) ||
		visit_collides(&line1) || visit_collides(&line2) ||
		visit_collides(&line3) || visit_collides(&line4);
}
Пример #12
0
int main(int argc, char *argv[]) {
	
	int maxX = 0;
	int maxY = 0;
	int minX = 0;
	int minY = 0;
	// Initialize lines vector with "random" numbers
    std::vector<Lines<int> > lines;
    Lines<int> line1(-533445, 535435, -23424, 312312);
    Lines<int> line2(343242, 223, 0, -42);
    Lines<int> line3(211, 25454, 44674, 1665432);
    Lines<int> line4(-142421, 4256, 98765432, 7653);
    lines.push_back(line1);
    lines.push_back(line2);
    lines.push_back(line3);
    lines.push_back(line4);
	
	// Normalize lines between -1 and 1 floats
	const std::vector<Lines<float> > normalizedLines = Algorithms::normalizeLines(lines, minX, maxX, minY, maxY);

    for(std::vector<Lines<float> >::const_iterator it = normalizedLines.begin(); it != normalizedLines.end(); ++it) {
        if (it->x1 > 1 || it->x1 < -1) {
			std::cout << "X1 value was out of bounds";
			return -1;
		} else if (it->x2 > 1 || it->x2 < -1) {
			std::cout << "X2 value was out of bounds";
			return -1;
		} else if (it->y1 > 1 || it->y1 < -1) {
			std::cout << "Y1 value was out of bounds";
			return -1;
		} else if (it->y2 > 1 || it->y2 < -1) {
			std::cout << "Y2 value was out of bounds";
			return -1;
		}
    }

    std::cout << "SUCCESSSSS!!";
    return 0;
}
Пример #13
0
/* same effect to test_rc_charge_discharge()
title rc charge discharge
.global gnd
vdc1 1 0 dc 5.000e+000
xspdt 1 2 0 spdt
rr1 2 3 5.000e+000
cc1 3 0 2.000e-001

.subckt spdt 1 2 3 params: vstatus=0 ron=1e-8 roff=1e30
r1 0 6 20
v1 6 0 dc {vstatus}
w0 2 1 v1 nc_contact
w1 2 3 v1 no_contact
.model no_contact csw (it=0.05 ih=0.025 ron={ron} roff={roff})
.model nc_contact csw (it=0.05 ih=0.025 ron={roff} roff={ron})
.ends

.control
stop when time = 5s
tran 100u 10s uic
alter v.xspdt.v1=-2
resume
plot all
.endc
*/
void test_rc_charge_discharge()
{
	ngdc dc("dc1", 5);
	ngspdt spdt("spdt");
	ngresistor r("r1", 5);
	ngcapacitor c("c1", 0.2);
	ngground gnd;

	ngline line1(dc.pos, spdt.throw1);
	ngline line2(spdt.pole, r.p1);
	ngline line3(r.p2, c.p1);
	ngline line4(c.p2, dc.neg);
	ngline line5(spdt.throw2, gnd.ground);
	ngline line0(dc.neg, gnd.ground);

	schema sch;
	sch.AddDevices(&dc, &spdt, &r, &c, &gnd, 0);
	sch.AddLines(&line1, &line2, &line3, &line4, &line5, &line0, 0);

	circuit cir(&sch);
	// transient analysis last 10 seconds
	cir.Tran("10", "1m");
	do 
	{
		Sleep(100);
		//charge 5 seconds. when time passes 5 seconds, start to discharge.
		static bool done = false;
		if (cir.CurrentValue("time") >= 5 && !done)
		{
			cir.SwitchOver(&spdt);
			Sleep(200);
			done = true;
		}
	} while (cir.IsRunning());
	cir.Do("plot all");
	getchar();
}
Пример #14
0
void ossimFeatherMosaic::ossimFeatherInputInformation::setVertexList(const std::vector<ossimIpt>& validVertices)
{
   const char* MODULE = "ossimFeatherMosaic::ossimFeatherInputInformation::setVertexList()";
   
   theValidVertices = validVertices;

   theCenter       = ossimDpt(0,0);
   theAxis1        = ossimDpt(1, 0);
   theAxis2        = ossimDpt(0, 1);
   theAxis1Length  = 1;
   theAxis2Length  = 1;

   double xSum=0.0, ySum=0.0;
   ossim_uint32 upperBound = (ossim_uint32)validVertices.size();
   if(upperBound)
   {
      for(ossim_uint32 index = 0; index < upperBound; ++index)
      {
         xSum += validVertices[index].x;
         ySum += validVertices[index].y;
      }

      theCenter.x = xSum/upperBound;
      theCenter.y = ySum/upperBound;

      // for now we just want a quick implementation of something
      // and we know that we have 4 vertices for the bounding valid
      // vertices.
      //
      if(upperBound == 4)
      {
         ossimDpt edgeDirection1 = validVertices[1] - validVertices[0];
         ossimDpt edgeDirection2 = validVertices[2] - validVertices[1];

         theAxis1 = ossimDpt(-edgeDirection1.y, edgeDirection1.x);
         
         theAxis2 = ossimDpt(-edgeDirection2.y, edgeDirection2.x);

         theAxis1 = theAxis1/theAxis1.length();
         theAxis2 = theAxis2/theAxis2.length();

         ossimLine line1(theCenter,
                         theCenter + theAxis1*2);
         ossimLine line2(validVertices[1],
                         validVertices[0]);
         ossimLine line3(theCenter,
                         theCenter + theAxis2*2);
         ossimLine line4(validVertices[2],
                         validVertices[1]);
         
         ossimDpt intersectionPoint1 = line1.intersectInfinite(line2);
         ossimDpt intersectionPoint2 = line3.intersectInfinite(line4);

         
         theAxis1Length = ossim::round<int>((theCenter-intersectionPoint1).length());
         theAxis2Length = ossim::round<int>((theCenter-intersectionPoint2).length());

          if(traceDebug())
          {
             CLOG << "theAxis1Length:       " << theAxis1Length << endl
                  << "theAxis2Length:       " << theAxis2Length << endl
                  << "center:               " << theCenter      << endl;
          }
      }
   }
}
Пример #15
0
QuadTreeNodeData::REGION_INTERSECTION_FLAG QuadTree::region_intersection(const iterator_base & it,  const CG_Region & region )
{
  RS_Hatch * hatch = region.hatch;
  if(!hatch->hasHole())
    return region_intersection(it,  region.contour_points );

  const RS_Vector * _p_tr = it->tr();
  const RS_Vector * _p_tl = it->tl();
  const RS_Vector * _p_br = it->br();
  const RS_Vector * _p_bl = it->bl();

  RS_Line line1(0, RS_LineData(*_p_bl, *_p_br));
  if(hatch->hasIntersectionWithEdge(&line1)) return QuadTreeNodeData::INTERSECTION_REGION;

  RS_Line line2(0, RS_LineData(*_p_br, *_p_tr));
  if(hatch->hasIntersectionWithEdge(&line2)) return QuadTreeNodeData::INTERSECTION_REGION;

  RS_Line line3(0, RS_LineData(*_p_tl, *_p_tr));
  if(hatch->hasIntersectionWithEdge(&line3)) return QuadTreeNodeData::INTERSECTION_REGION;

  RS_Line line4(0, RS_LineData(*_p_bl, *_p_tl));
  if(hatch->hasIntersectionWithEdge(&line4)) return QuadTreeNodeData::INTERSECTION_REGION;

  bool this_point_on_hatch;
  if(RS_Information::isPointInsideContour(*_p_bl,  hatch, &this_point_on_hatch))
    return QuadTreeNodeData::IN_REGION;

  if(it->has_point(hatch->getData().internal_point))
    return  QuadTreeNodeData::COVER_REGION;

  return QuadTreeNodeData::OUT_REGION;

  /*
    unsigned int n_point_in_region = 0;
    bool has_point_on_region=false;

    {
      bool this_point_on_hatch;

      n_point_in_region += RS_Information::isPointInsideContour(*_p_tr,  hatch, &this_point_on_hatch);
      if(this_point_on_hatch) has_point_on_region=true;

      n_point_in_region += RS_Information::isPointInsideContour(*_p_tl,  hatch, &this_point_on_hatch);
      if(this_point_on_hatch) has_point_on_region=true;

      n_point_in_region += RS_Information::isPointInsideContour(*_p_br,  hatch, &this_point_on_hatch);
      if(this_point_on_hatch) has_point_on_region=true;

      n_point_in_region += RS_Information::isPointInsideContour(*_p_bl,  hatch, &this_point_on_hatch);
      if(this_point_on_hatch) has_point_on_region=true;
    }

  std::cout<<n_point_in_region<<std::endl;
    if(has_point_on_region)
    {
      std::cout<<"INTERSECTION_REGION"<<std::endl;
      return QuadTreeNodeData::INTERSECTION_REGION;
    }

    if(n_point_in_region==4)
    {
      return QuadTreeNodeData::IN_REGION;
    }

    if(n_point_in_region==0)
    {
      if(it->has_point(hatch->getData().internal_point))
        return  QuadTreeNodeData::COVER_REGION;
      else return QuadTreeNodeData::OUT_REGION;
    }

    if(n_point_in_region>0 && n_point_in_region<4)
      return QuadTreeNodeData::INTERSECTION_REGION;
  */

}
Пример #16
0
void KisToolFreehandHelper::paintBezierSegment(KisPaintInformation pi1, KisPaintInformation pi2,
        QPointF tangent1, QPointF tangent2)
{
    if (tangent1.isNull() || tangent2.isNull()) return;

    const qreal maxSanePoint = 1e6;

    QPointF controlTarget1;
    QPointF controlTarget2;

    // Shows the direction in which control points go
    QPointF controlDirection1 = pi1.pos() + tangent1;
    QPointF controlDirection2 = pi2.pos() - tangent2;

    // Lines in the direction of the control points
    QLineF line1(pi1.pos(), controlDirection1);
    QLineF line2(pi2.pos(), controlDirection2);

    // Lines to check whether the control points lay on the opposite
    // side of the line
    QLineF line3(controlDirection1, controlDirection2);
    QLineF line4(pi1.pos(), pi2.pos());

    QPointF intersection;
    if (line3.intersect(line4, &intersection) == QLineF::BoundedIntersection) {
        qreal controlLength = line4.length() / 2;

        line1.setLength(controlLength);
        line2.setLength(controlLength);

        controlTarget1 = line1.p2();
        controlTarget2 = line2.p2();
    } else {
        QLineF::IntersectType type = line1.intersect(line2, &intersection);

        if (type == QLineF::NoIntersection ||
                intersection.manhattanLength() > maxSanePoint) {

            intersection = 0.5 * (pi1.pos() + pi2.pos());
//            dbgKrita << "WARINING: there is no intersection point "
//                     << "in the basic smoothing algoriths";
        }

        controlTarget1 = intersection;
        controlTarget2 = intersection;
    }

    // shows how near to the controlTarget the value raises
    qreal coeff = 0.8;

    qreal velocity1 = QLineF(QPointF(), tangent1).length();
    qreal velocity2 = QLineF(QPointF(), tangent2).length();

    if (velocity1 == 0.0 || velocity2 == 0.0) {
        velocity1 = 1e-6;
        velocity2 = 1e-6;
        warnKrita << "WARNING: Basic Smoothing: Velocity is Zero! Please report a bug:" << ppVar(velocity1) << ppVar(velocity2);
    }

    qreal similarity = qMin(velocity1/velocity2, velocity2/velocity1);

    // the controls should not differ more than 50%
    similarity = qMax(similarity, qreal(0.5));

    // when the controls are symmetric, their size should be smaller
    // to avoid corner-like curves
    coeff *= 1 - qMax(qreal(0.0), similarity - qreal(0.8));

    Q_ASSERT(coeff > 0);


    QPointF control1;
    QPointF control2;

    if (velocity1 > velocity2) {
        control1 = pi1.pos() * (1.0 - coeff) + coeff * controlTarget1;
        coeff *= similarity;
        control2 = pi2.pos() * (1.0 - coeff) + coeff * controlTarget2;
    } else {
        control2 = pi2.pos() * (1.0 - coeff) + coeff * controlTarget2;
        coeff *= similarity;
        control1 = pi1.pos() * (1.0 - coeff) + coeff * controlTarget1;
    }

    paintBezierCurve(pi1,
                     control1,
                     control2,
                     pi2);
}