static void cubicQuadIntersection(skiatest::Reporter* reporter, int index) {
    int iIndex = static_cast<int>(index);
    const SkDCubic& cubic = quadCubicTests[index].cubic;
    SkASSERT(ValidCubic(cubic));
    const SkDQuad& quad = quadCubicTests[index].quad;
    SkASSERT(ValidQuad(quad));
    SkReduceOrder reduce1;
    SkReduceOrder reduce2;
    int order1 = reduce1.reduce(cubic, SkReduceOrder::kNo_Quadratics);
    int order2 = reduce2.reduce(quad);
    if (order1 != 4) {
        SkDebugf("[%d] cubic order=%d\n", iIndex, order1);
        REPORTER_ASSERT(reporter, 0);
    }
    if (order2 != 3) {
        SkDebugf("[%d] quad order=%d\n", iIndex, order2);
        REPORTER_ASSERT(reporter, 0);
    }
    SkIntersections i;
    int roots = i.intersect(cubic, quad);
    for (int pt = 0; pt < roots; ++pt) {
        double tt1 = i[0][pt];
        SkDPoint xy1 = cubic.ptAtT(tt1);
        double tt2 = i[1][pt];
        SkDPoint xy2 = quad.ptAtT(tt2);
        if (!xy1.approximatelyEqual(xy2)) {
            SkDebugf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
                __FUNCTION__, iIndex, pt, tt1, xy1.fX, xy1.fY, tt2, xy2.fX, xy2.fY);
        }
        REPORTER_ASSERT(reporter, xy1.approximatelyEqual(xy2));
    }
    reporter->bumpTestCount();
}
static void coincidentTestOne(skiatest::Reporter* reporter, int test1, int test2) {
    const SkDQuad& quad1 = coincidentTestSet[test1];
    SkASSERT(ValidQuad(quad1));
    const SkDQuad& quad2 = coincidentTestSet[test2];
    SkASSERT(ValidQuad(quad2));
    SkIntersections intersections2;
    intersections2.intersect(quad1, quad2);
    REPORTER_ASSERT(reporter, intersections2.coincidentUsed() == 2);
    REPORTER_ASSERT(reporter, intersections2.used() == 2);
    for (int pt = 0; pt < intersections2.coincidentUsed(); ++pt) {
        double tt1 = intersections2[0][pt];
        double tt2 = intersections2[1][pt];
        SkDPoint pt1 = quad1.ptAtT(tt1);
        SkDPoint pt2 = quad2.ptAtT(tt2);
        REPORTER_ASSERT(reporter, pt1.approximatelyEqual(pt2));
    }
}
static void standardTestCases(skiatest::Reporter* reporter) {
    bool showSkipped = false;
    for (size_t index = 0; index < quadraticTests_count; ++index) {
        const SkDQuad& quad1 = quadraticTests[index][0];
        SkASSERT(ValidQuad(quad1));
        const SkDQuad& quad2 = quadraticTests[index][1];
        SkASSERT(ValidQuad(quad2));
        SkReduceOrder reduce1, reduce2;
        int order1 = reduce1.reduce(quad1);
        int order2 = reduce2.reduce(quad2);
        if (order1 < 3) {
            if (showSkipped) {
                SkDebugf("[%d] quad1 order=%d\n", static_cast<int>(index), order1);
            }
        }
        if (order2 < 3) {
            if (showSkipped) {
                SkDebugf("[%d] quad2 order=%d\n", static_cast<int>(index), order2);
            }
        }
        if (order1 == 3 && order2 == 3) {
            SkIntersections intersections;
            intersections.intersect(quad1, quad2);
            if (intersections.used() > 0) {
                for (int pt = 0; pt < intersections.used(); ++pt) {
                    double tt1 = intersections[0][pt];
                    SkDPoint xy1 = quad1.ptAtT(tt1);
                    double tt2 = intersections[1][pt];
                    SkDPoint xy2 = quad2.ptAtT(tt2);
                    if (!xy1.approximatelyEqual(xy2)) {
                        SkDebugf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
                                __FUNCTION__, static_cast<int>(index), pt, tt1, xy1.fX, xy1.fY,
                                tt2, xy2.fX, xy2.fY);
                        REPORTER_ASSERT(reporter, 0);
                    }
                }
            }
        }
    }
}
static void oneOffTest1(skiatest::Reporter* reporter, size_t outer, size_t inner) {
    const SkDQuad& quad1 = testSet[outer];
    SkASSERT(ValidQuad(quad1));
    const SkDQuad& quad2 = testSet[inner];
    SkASSERT(ValidQuad(quad2));
    SkIntersections intersections2;
    intersections2.intersect(quad1, quad2);
    for (int pt = 0; pt < intersections2.used(); ++pt) {
        double tt1 = intersections2[0][pt];
        SkDPoint xy1 = quad1.ptAtT(tt1);
        double tt2 = intersections2[1][pt];
        SkDPoint xy2 = quad2.ptAtT(tt2);
        if (!xy1.approximatelyEqual(xy2)) {
            SkDebugf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
                    __FUNCTION__, static_cast<int>(outer), static_cast<int>(inner),
                    tt1, xy1.fX, xy1.fY, tt2, xy2.fX, xy2.fY);
            REPORTER_ASSERT(reporter, 0);
        }
#if ONE_OFF_DEBUG
        SkDebugf("%s [%d][%d] t1=%1.9g (%1.9g, %1.9g) t2=%1.9g\n", __FUNCTION__,
            outer, inner, tt1, xy1.fX, xy1.fY, tt2);
#endif
    }
}
Esempio n. 5
0
Error
_dxf_quadsToQmesh (xfieldT *xf, void *globals)
{
  DEFGLOBALDATA(globals) ;
  Quadruple *neighbors ;       /* neighbors array gives a quad's neighbors  */
  Qstrip *stripArray = 0 ;     /* temp array of strips                      */
  int point[MaxQstripSize] ;   /* array into which to build point list      */
  char *usedArray = 0 ;        /* marks quads already used                  */
  int nStrips = 0 ;            /* number of strips generated                */
  int nStrippedPts = 0 ;       /* number of points stripped                 */
  int nPtsInStrip ;            /* number of points in current strip         */
  int start_quad ;             /* first quad of the strip                   */
  int quad ;                   /* the current quad                          */
  int dir, i0, i1, i2, i3 ;    /* the 4 indexes into quads[quad].p[?]       */
  int prev_quad, prev_i0,      /* used to determine the same current info   */
      prev_i1,prev_i2,prev_i3 ;
  Quadruple *quads ;           /* array of original quad connections        */
  int nquads ;                 /* number of original quad connections       */
  int i, j, k ;                /* misc. indices                             */
  QMesh qmesh = NULL;
  dxObject qmesho = NULL;

  ENTRY(("_dxf_quadsToQmesh(0x%x)", xf));

  qmesho = _dxf_QueryObject(MESHHASH, (dxObject)xf->field);
  if (qmesho)
  {
      xf->meshObject = DXReference(qmesho);
      qmesh = (QMesh)DXGetPrivateData((Private)qmesho);
      _installQMeshInfo(xf, qmesh);

      return OK;
  }

  if (xf->connectionType != ct_quads)
    {
      EXIT(("xf->connectionType not ct_quads"));
      return OK ;
    }

  PRINT(("invalid connections: %d",
	   xf->invCntns? DXGetInvalidCount(xf->invCntns): 0)) ;

  neighbors = getNeighbors(xf);

  /* get quad connection info; quad connections are replaced by strips */
  quads = DXGetArrayData(xf->connections_array) ;
  nquads = xf->nconnections ;
  /*npoints = xf->npositions ;*/

  xf->origNConnections = nquads;
  xf->origConnections_array = xf->connections_array;
  xf->connections_array = NULL;

  /* allocate temporary array to hold maximum possible number of strips */
  if (!(stripArray = (Qstrip *) tdmAllocate(sizeof(Qstrip) * nquads)))
    {
      PRINT(("out of memory"));
      DXErrorGoto (ERROR_NO_MEMORY, "#13000") ;
    }

  if (neighbors)
    {
      /* quad connections expressed explicitly, we need usedArray */
      if (!(usedArray = tdmAllocateZero(sizeof(char) * Bytes(nquads))))
	{
	  PRINT(("out of memory"));
	  DXErrorGoto (ERROR_NO_MEMORY, "#13000") ;
	}

      /* strip the field, placing strip info into temporary arrays */
      for (start_quad = 0; start_quad < nquads; start_quad++)
	{
	  if (GoodQuad(start_quad))
	    {
	      nPtsInStrip = 0 ;
	      quad = start_quad ;
	      InitFirstQuad(i0,i1,i2,i3) ; /* pick 1st quad initial vertices */
	      AddPoint(quad,i1) ;          /* add the 1st two...             */
	      AddPoint(quad,i0) ;          /* ...points to the mesh          */
	      while (quad >= 0)            /* while there's a valid quad...  */
		{
		  AddPoint(quad,i3) ;      /*  add another quad to the strip */
		  AddPoint(quad,i2) ;
		  MarkQuad(quad) ;         /*  mark it as used               */
		  NextQuad(quad) ;         /*  move on to next quad          */
		}

	      /* save strip points */
	      AllocateAndCopyQstripPointArray() ;
	    }
	}
      tdmFree((Pointer)usedArray) ;
      usedArray = NULL;
    }
  else
    {
      /* quad connections expressed in compact mesh array form */
      int n, counts[100] ;

      if (!DXQueryGridConnections (xf->origConnections_array, &n, counts) || n != 2)
	  DXErrorGoto (ERROR_INTERNAL, "#13140") ;

      PRINT(("counts[0] = %d", counts[0]));
      PRINT(("counts[1] = %d", counts[1]));

      for (n = 0, i = 0 ; i < counts[0]-1 ; i++)
	{
	  j = 0 ;
	  while (j < counts[1]-1)
	    {
	      for ( ; j < counts[1]-1 && !ValidQuad(xf->invCntns, n) ; j++, n++)
		  /* skip invalid quads up to end of row/column */ ;

	      if (j == counts[1]-1)
		  break ;

	      /* start triangle strip */
	      nPtsInStrip = 0 ;
	      point[nPtsInStrip++] = n + i ;
	      point[nPtsInStrip++] = n + i + counts[1] ;

	      while (j < counts[1]-1 &&
		     nPtsInStrip < MaxQstripSize &&
		     ValidQuad(xf->invCntns, n))
		{
		  /* add valid quads up to end of row/column or strip limit  */
		  point[nPtsInStrip++] = n + i + 1 ;
		  point[nPtsInStrip++] = n + i + 1 + counts[1] ;
		  j++ ; n++ ;
		}

	      /* save strip points */
	      AllocateAndCopyQstripPointArray() ;
	    }
	}
    }

  PRINT(("stripped %d quadrangles", (nStrippedPts - 2*nStrips)/2));
  PRINT(("generated %d triangle strips", nStrips));
  PRINT(("average number of triangles per strip: %f",
	   nStrips? (nStrippedPts - 2*nStrips)/(float)nStrips: 0));

  if (! _newQMesh(nStrips, nStrippedPts, &qmesh, &qmesho))
      goto error;

  for (i=j=k=0 ; i<nStrips ; i++)
    {
      qmesh->meshes[j++] = k;
      qmesh->meshes[j++] = stripArray[i].points;
      memcpy(qmesh->connections+k, stripArray[i].point, stripArray[i].points*sizeof(int));
      k += stripArray[i].points;
    }

  _dxf_InsertObject(MESHHASH, (dxObject)(xf->field), (dxObject)qmesho);
  xf->meshObject = DXReference(qmesho);
  _installQMeshInfo(xf, qmesh);

  /* free temporary array of strips */
  if (usedArray)
      tdmFree((Pointer)usedArray);
  if (stripArray)
      FreeTempStrips() ;

  EXIT(("OK"));
  return OK ;

 error:
  if (usedArray)
      tdmFree((Pointer)usedArray);
  if (stripArray)
      FreeTempStrips() ;

  EXIT(("ERROR"));
  return 0 ;
}
static void PathOpsDRectTest(skiatest::Reporter* reporter) {
    size_t index;
    SkDRect rect, rect2;
    for (index = 0; index < lineTests_count; ++index) {
        const SkDLine& line = lineTests[index];
        SkASSERT(ValidLine(line));
        rect.setBounds(line);
        REPORTER_ASSERT(reporter, rect.fLeft == SkTMin(line[0].fX, line[1].fX));
        REPORTER_ASSERT(reporter, rect.fTop == SkTMin(line[0].fY, line[1].fY));
        REPORTER_ASSERT(reporter, rect.fRight == SkTMax(line[0].fX, line[1].fX));
        REPORTER_ASSERT(reporter, rect.fBottom == SkTMax(line[0].fY, line[1].fY));
        rect2.set(line[0]);
        rect2.add(line[1]);
        REPORTER_ASSERT(reporter, rect2.fLeft == SkTMin(line[0].fX, line[1].fX));
        REPORTER_ASSERT(reporter, rect2.fTop == SkTMin(line[0].fY, line[1].fY));
        REPORTER_ASSERT(reporter, rect2.fRight == SkTMax(line[0].fX, line[1].fX));
        REPORTER_ASSERT(reporter, rect2.fBottom == SkTMax(line[0].fY, line[1].fY));
        REPORTER_ASSERT(reporter, rect.contains(line[0]));
        REPORTER_ASSERT(reporter, rect.intersects(&rect2));
    }
    for (index = 0; index < quadTests_count; ++index) {
        const SkDQuad& quad = quadTests[index];
        SkASSERT(ValidQuad(quad));
        rect.setRawBounds(quad);
        REPORTER_ASSERT(reporter, rect.fLeft == SkTMin(quad[0].fX,
                SkTMin(quad[1].fX, quad[2].fX)));
        REPORTER_ASSERT(reporter, rect.fTop == SkTMin(quad[0].fY,
                SkTMin(quad[1].fY, quad[2].fY)));
        REPORTER_ASSERT(reporter, rect.fRight == SkTMax(quad[0].fX,
                SkTMax(quad[1].fX, quad[2].fX)));
        REPORTER_ASSERT(reporter, rect.fBottom == SkTMax(quad[0].fY,
                SkTMax(quad[1].fY, quad[2].fY)));
        rect2.setBounds(quad);
        REPORTER_ASSERT(reporter, rect.intersects(&rect2));
        // FIXME: add a recursive box subdivision method to verify that tight bounds is correct
        SkDPoint leftTop = {rect2.fLeft, rect2.fTop};
        REPORTER_ASSERT(reporter, rect.contains(leftTop));
        SkDPoint rightBottom = {rect2.fRight, rect2.fBottom};
        REPORTER_ASSERT(reporter, rect.contains(rightBottom));
    }
    for (index = 0; index < cubicTests_count; ++index) {
        const SkDCubic& cubic = cubicTests[index];
        SkASSERT(ValidCubic(cubic));
        rect.setRawBounds(cubic);
        REPORTER_ASSERT(reporter, rect.fLeft == SkTMin(cubic[0].fX,
                SkTMin(cubic[1].fX, SkTMin(cubic[2].fX, cubic[3].fX))));
        REPORTER_ASSERT(reporter, rect.fTop == SkTMin(cubic[0].fY,
                SkTMin(cubic[1].fY, SkTMin(cubic[2].fY, cubic[3].fY))));
        REPORTER_ASSERT(reporter, rect.fRight == SkTMax(cubic[0].fX,
                SkTMax(cubic[1].fX, SkTMax(cubic[2].fX, cubic[3].fX))));
        REPORTER_ASSERT(reporter, rect.fBottom == SkTMax(cubic[0].fY,
                SkTMax(cubic[1].fY, SkTMax(cubic[2].fY, cubic[3].fY))));
        rect2.setBounds(cubic);
        REPORTER_ASSERT(reporter, rect.intersects(&rect2));
        // FIXME: add a recursive box subdivision method to verify that tight bounds is correct
        SkDPoint leftTop = {rect2.fLeft, rect2.fTop};
        REPORTER_ASSERT(reporter, rect.contains(leftTop));
        SkDPoint rightBottom = {rect2.fRight, rect2.fBottom};
        REPORTER_ASSERT(reporter, rect.contains(rightBottom));
    }
}
Esempio n. 7
0
static void setup(const SortSet* set, const size_t idx,
        SkOpSegment* seg, int* ts, const SkPoint& startPt) {
    SkPoint start, end;
    const SkPoint* data = set[idx].ptData;
    bool useIntersectPt = startPt.fX != 0 || startPt.fY != 0;
    if (useIntersectPt) {
        start = startPt;
        end = set[idx].endPt;
    }
    switch(set[idx].ptCount) {
        case 2: {
            SkASSERT(ValidPoints(data, 2));
            seg->addLine(data, false, false);
            SkDLine dLine;
            dLine.set(set[idx].ptData);
            SkASSERT(ValidLine(dLine));
            if (useIntersectPt) {
                break;
            }
            start = dLine.ptAtT(set[idx].tStart).asSkPoint();
            end = dLine.ptAtT(set[idx].tEnd).asSkPoint();
            } break;
        case 3: {
            SkASSERT(ValidPoints(data, 3));
            seg->addQuad(data, false, false);
            SkDQuad dQuad;
            dQuad.set(set[idx].ptData);
            SkASSERT(ValidQuad(dQuad));
             if (useIntersectPt) {
                break;
            }
            start = dQuad.ptAtT(set[idx].tStart).asSkPoint();
            end = dQuad.ptAtT(set[idx].tEnd).asSkPoint();
            } break;
        case 4: {
            SkASSERT(ValidPoints(data, 4));
            seg->addCubic(data, false, false);
            SkDCubic dCubic;
            dCubic.set(set[idx].ptData);
            SkASSERT(ValidCubic(dCubic));
            if (useIntersectPt) {
                break;
            }
            start = dCubic.ptAtT(set[idx].tStart).asSkPoint();
            end = dCubic.ptAtT(set[idx].tEnd).asSkPoint();
            } break;
    }
    double tStart = set[idx].tStart;
    double tEnd = set[idx].tEnd;
    seg->addT(NULL, start, tStart);
    seg->addT(NULL, end, tEnd);
    if (tStart != 0 && tEnd != 0) {
        seg->addT(NULL, set[idx].ptData[0], 0);
    }
    if (tStart != 1 && tEnd != 1) {
        seg->addT(NULL, set[idx].ptData[set[idx].ptCount - 1], 1);
    }
    int tIndex = 0;
    ts[0] = 0;
    ts[1] = 1;
    do {
        if (seg->t(tIndex) == set[idx].tStart) {
            ts[0] = tIndex;
        }
        if (seg->t(tIndex) == set[idx].tEnd) {
            ts[1] = tIndex;
        }
        if (seg->t(tIndex) >= 1) {
            break;
        }
    } while (++tIndex);
}