예제 #1
0
파일: scanfill.c 프로젝트: 244xiao/blender
static void testvertexnearedge(ScanFillContext *sf_ctx)
{
	/* only vertices with (->h == 1) are being tested for
	 * being close to an edge, if true insert */

	ScanFillVert *eve;
	ScanFillEdge *eed, *ed1;

	for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
		if (eve->edge_tot == 1) {
			/* find the edge which has vertex eve,
			 * note: we _know_ this will crash if 'ed1' becomes NULL
			 * but this will never happen. */
			for (ed1 = sf_ctx->filledgebase.first;
			     !(ed1->v1 == eve || ed1->v2 == eve);
			     ed1 = ed1->next)
			{
				/* do nothing */
			}

			if (ed1->v1 == eve) {
				ed1->v1 = ed1->v2;
				ed1->v2 = eve;
			}

			for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
				if (eve != eed->v1 && eve != eed->v2 && eve->poly_nr == eed->poly_nr) {
					if (compare_v2v2(eve->xy, eed->v1->xy, SF_EPSILON)) {
						ed1->v2 = eed->v1;
						eed->v1->edge_tot++;
						eve->edge_tot = 0;
						break;
					}
					else if (compare_v2v2(eve->xy, eed->v2->xy, SF_EPSILON)) {
						ed1->v2 = eed->v2;
						eed->v2->edge_tot++;
						eve->edge_tot = 0;
						break;
					}
					else {
						if (boundinsideEV(eed, eve)) {
							const float dist = dist_to_line_v2(eed->v1->xy, eed->v2->xy, eve->xy);
							if (dist < SF_EPSILON) {
								/* new edge */
								ed1 = BLI_scanfill_edge_add(sf_ctx, eed->v1, eve);
								
								/* printf("fill: vertex near edge %x\n", eve); */
								ed1->f = 0;
								ed1->poly_nr = eed->poly_nr;
								eed->v1 = eve;
								eve->edge_tot = 3;
								break;
							}
						}
					}
				}
			}
		}
	}
}
예제 #2
0
static void testvertexnearedge(ScanFillContext *sf_ctx)
{
	/* only vertices with ->h==1 are being tested for
	 * being close to an edge, if true insert */

	ScanFillVert *eve;
	ScanFillEdge *eed, *ed1;

	for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
		if (eve->h == 1) {
			/* find the edge which has vertex eve */
			ed1 = sf_ctx->filledgebase.first;
			while (ed1) {
				if (ed1->v1 == eve || ed1->v2 == eve) break;
				ed1 = ed1->next;
			}
			if (ed1->v1 == eve) {
				ed1->v1 = ed1->v2;
				ed1->v2 = eve;
			}

			for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
				if (eve != eed->v1 && eve != eed->v2 && eve->poly_nr == eed->poly_nr) {
					if (compare_v3v3(eve->co, eed->v1->co, SF_EPSILON)) {
						ed1->v2 = eed->v1;
						eed->v1->h++;
						eve->h = 0;
						break;
					}
					else if (compare_v3v3(eve->co, eed->v2->co, SF_EPSILON)) {
						ed1->v2 = eed->v2;
						eed->v2->h++;
						eve->h = 0;
						break;
					}
					else {
						if (boundinsideEV(eed, eve)) {
							const float dist = dist_to_line_v2(eed->v1->xy, eed->v2->xy, eve->xy);
							if (dist < SF_EPSILON) {
								/* new edge */
								ed1 = BLI_addfilledge(sf_ctx, eed->v1, eve);
								
								/* printf("fill: vertex near edge %x\n",eve); */
								ed1->f = 0;
								ed1->poly_nr = eed->poly_nr;
								eed->v1 = eve;
								eve->h = 3;
								break;
							}
						}
					}
				}
			}
		}
	}
}
예제 #3
0
static void testvertexnearedge(void)
{
	/* only vertices with ->h==1 are being tested for
		being close to an edge, if true insert */

	EditVert *eve;
	EditEdge *eed,*ed1;
	float dist,vec1[2],vec2[2],vec3[2];

	eve= fillvertbase.first;
	while(eve) {
		if(eve->h==1) {
			vec3[0]= eve->co[cox];
			vec3[1]= eve->co[coy];
			/* find the edge which has vertex eve */
			ed1= filledgebase.first;
			while(ed1) {
				if(ed1->v1==eve || ed1->v2==eve) break;
				ed1= ed1->next;
			}
			if(ed1->v1==eve) {
				ed1->v1= ed1->v2;
				ed1->v2= eve;
			}
			eed= filledgebase.first;
			while(eed) {
				if(eve!=eed->v1 && eve!=eed->v2 && eve->xs==eed->f1) {
					if(compare_v3v3(eve->co,eed->v1->co, COMPLIMIT)) {
						ed1->v2= eed->v1;
						eed->v1->h++;
						eve->h= 0;
						break;
					}
					else if(compare_v3v3(eve->co,eed->v2->co, COMPLIMIT)) {
						ed1->v2= eed->v2;
						eed->v2->h++;
						eve->h= 0;
						break;
					}
					else {
						vec1[0]= eed->v1->co[cox];
						vec1[1]= eed->v1->co[coy];
						vec2[0]= eed->v2->co[cox];
						vec2[1]= eed->v2->co[coy];
						if(boundinsideEV(eed,eve)) {
							dist= dist_to_line_v2(vec1,vec2,vec3);
							if(dist<COMPLIMIT) {
								/* new edge */
								ed1= BLI_addfilledge(eed->v1, eve);
								
								/* printf("fill: vertex near edge %x\n",eve); */
								ed1->f= ed1->h= 0;
								ed1->f1= eed->f1;
								eed->v1= eve;
								eve->h= 3;
								break;
							}
						}
					}
				}
				eed= eed->next;
			}
		}
		eve= eve->next;
	}
}
예제 #4
0
static void freetypechar_to_vchar(FT_Face face, FT_ULong charcode, VFontData *vfd)
{
	/* Blender */
	struct Nurb *nu;
	struct VChar *che;
	struct BezTriple *bezt;

	/* Freetype2 */
	FT_GlyphSlot glyph;
	FT_UInt glyph_index;
	FT_Outline ftoutline;
	float scale, height;
	float dx, dy;
	int j, k, l, m = 0;

	/* adjust font size */
	height = ((double) face->bbox.yMax - (double) face->bbox.yMin);
	if (height != 0.0f)
		scale = 1.0f / height;
	else
		scale = 1.0f / 1000.0f;

	/*
	 * Generate the character 3D data
	 *
	 * Get the FT Glyph index and load the Glyph */
	glyph_index = FT_Get_Char_Index(face, charcode);
	err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);

	/* If loading succeeded, convert the FT glyph to the internal format */
	if (!err) {
		int *npoints;
		int *onpoints;

		/* First we create entry for the new character to the character list */
		che = (VChar *) MEM_callocN(sizeof(struct VChar), "objfnt_char");
		BLI_addtail(&vfd->characters, che);

		/* Take some data for modifying purposes */
		glyph = face->glyph;
		ftoutline = glyph->outline;

		/* Set the width and character code */
		che->index = charcode;
		che->width = glyph->advance.x * scale;

		/* Start converting the FT data */
		npoints = (int *)MEM_callocN((ftoutline.n_contours) * sizeof(int), "endpoints");
		onpoints = (int *)MEM_callocN((ftoutline.n_contours) * sizeof(int), "onpoints");

		/* calculate total points of each contour */
		for (j = 0; j < ftoutline.n_contours; j++) {
			if (j == 0)
				npoints[j] = ftoutline.contours[j] + 1;
			else
				npoints[j] = ftoutline.contours[j] - ftoutline.contours[j - 1];
		}

		/* get number of on-curve points for beziertriples (including conic virtual on-points) */
		for (j = 0; j < ftoutline.n_contours; j++) {
			for (k = 0; k < npoints[j]; k++) {
				l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;

				if (ftoutline.tags[l] == FT_Curve_Tag_On)
					onpoints[j]++;

				if (k < npoints[j] - 1) {
					if (ftoutline.tags[l] == FT_Curve_Tag_Conic &&
					    ftoutline.tags[l + 1] == FT_Curve_Tag_Conic)
					{
						onpoints[j]++;
					}
				}
			}
		}

		/* contour loop, bezier & conic styles merged */
		for (j = 0; j < ftoutline.n_contours; j++) {
			/* add new curve */
			nu  =  (Nurb *)MEM_callocN(sizeof(struct Nurb), "objfnt_nurb");
			bezt = (BezTriple *)MEM_callocN((onpoints[j]) * sizeof(BezTriple), "objfnt_bezt");
			BLI_addtail(&che->nurbsbase, nu);

			nu->type = CU_BEZIER;
			nu->pntsu = onpoints[j];
			nu->resolu = 8;
			nu->flag = CU_2D;
			nu->flagu = CU_NURB_CYCLIC;
			nu->bezt = bezt;

			/* individual curve loop, start-end */
			for (k = 0; k < npoints[j]; k++) {
				if (j > 0) l = k + ftoutline.contours[j - 1] + 1; else l = k;
				if (k == 0) m = l;

				/* virtual conic on-curve points */
				if (k < npoints[j] - 1) {
					if (ftoutline.tags[l] == FT_Curve_Tag_Conic && ftoutline.tags[l + 1] == FT_Curve_Tag_Conic) {
						dx = (ftoutline.points[l].x + ftoutline.points[l + 1].x) * scale / 2.0f;
						dy = (ftoutline.points[l].y + ftoutline.points[l + 1].y) * scale / 2.0f;

						/* left handle */
						bezt->vec[0][0] = (dx + (2 * ftoutline.points[l].x) * scale) / 3.0f;
						bezt->vec[0][1] = (dy + (2 * ftoutline.points[l].y) * scale) / 3.0f;

						/* midpoint (virtual on-curve point) */
						bezt->vec[1][0] = dx;
						bezt->vec[1][1] = dy;

						/* right handle */
						bezt->vec[2][0] = (dx + (2 * ftoutline.points[l + 1].x) * scale) / 3.0f;
						bezt->vec[2][1] = (dy + (2 * ftoutline.points[l + 1].y) * scale) / 3.0f;

						bezt->h1 = bezt->h2 = HD_ALIGN;
						bezt->radius = 1.0f;
						bezt++;
					}
				}

				/* on-curve points */
				if (ftoutline.tags[l] == FT_Curve_Tag_On) {
					/* left handle */
					if (k > 0) {
						if (ftoutline.tags[l - 1] == FT_Curve_Tag_Cubic) {
							bezt->vec[0][0] = ftoutline.points[l - 1].x * scale;
							bezt->vec[0][1] = ftoutline.points[l - 1].y * scale;
							bezt->h1 = HD_FREE;
						}
						else if (ftoutline.tags[l - 1] == FT_Curve_Tag_Conic) {
							bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l - 1].x)) * scale / 3.0f;
							bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l - 1].y)) * scale / 3.0f;
							bezt->h1 = HD_FREE;
						}
						else {
							bezt->vec[0][0] = ftoutline.points[l].x * scale - (ftoutline.points[l].x - ftoutline.points[l - 1].x) * scale / 3.0f;
							bezt->vec[0][1] = ftoutline.points[l].y * scale - (ftoutline.points[l].y - ftoutline.points[l - 1].y) * scale / 3.0f;
							bezt->h1 = HD_VECT;
						}
					}
					else { /* first point on curve */
						if (ftoutline.tags[ftoutline.contours[j]] == FT_Curve_Tag_Cubic) {
							bezt->vec[0][0] = ftoutline.points[ftoutline.contours[j]].x * scale;
							bezt->vec[0][1] = ftoutline.points[ftoutline.contours[j]].y * scale;
							bezt->h1 = HD_FREE;
						}
						else if (ftoutline.tags[ftoutline.contours[j]] == FT_Curve_Tag_Conic) {
							bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[ftoutline.contours[j]].x)) * scale / 3.0f;
							bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[ftoutline.contours[j]].y)) * scale / 3.0f;
							bezt->h1 = HD_FREE;
						}
						else {
							bezt->vec[0][0] = ftoutline.points[l].x * scale - (ftoutline.points[l].x - ftoutline.points[ftoutline.contours[j]].x) * scale / 3.0f;
							bezt->vec[0][1] = ftoutline.points[l].y * scale - (ftoutline.points[l].y - ftoutline.points[ftoutline.contours[j]].y) * scale / 3.0f;
							bezt->h1 = HD_VECT;
						}
					}

					/* midpoint (on-curve point) */
					bezt->vec[1][0] = ftoutline.points[l].x * scale;
					bezt->vec[1][1] = ftoutline.points[l].y * scale;

					/* right handle */
					if (k < (npoints[j] - 1)) {
						if (ftoutline.tags[l + 1] == FT_Curve_Tag_Cubic) {
							bezt->vec[2][0] = ftoutline.points[l + 1].x * scale;
							bezt->vec[2][1] = ftoutline.points[l + 1].y * scale;
							bezt->h2 = HD_FREE;
						}
						else if (ftoutline.tags[l + 1] == FT_Curve_Tag_Conic) {
							bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l + 1].x)) * scale / 3.0f;
							bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l + 1].y)) * scale / 3.0f;
							bezt->h2 = HD_FREE;
						}
						else {
							bezt->vec[2][0] = ftoutline.points[l].x * scale - (ftoutline.points[l].x - ftoutline.points[l + 1].x) * scale / 3.0f;
							bezt->vec[2][1] = ftoutline.points[l].y * scale - (ftoutline.points[l].y - ftoutline.points[l + 1].y) * scale / 3.0f;
							bezt->h2 = HD_VECT;
						}
					}
					else { /* last point on curve */
						if (ftoutline.tags[m] == FT_Curve_Tag_Cubic) {
							bezt->vec[2][0] = ftoutline.points[m].x * scale;
							bezt->vec[2][1] = ftoutline.points[m].y * scale;
							bezt->h2 = HD_FREE;
						}
						else if (ftoutline.tags[m] == FT_Curve_Tag_Conic) {
							bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[m].x)) * scale / 3.0f;
							bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[m].y)) * scale / 3.0f;
							bezt->h2 = HD_FREE;
						}
						else {
							bezt->vec[2][0] = ftoutline.points[l].x * scale - (ftoutline.points[l].x - ftoutline.points[m].x) * scale / 3.0f;
							bezt->vec[2][1] = ftoutline.points[l].y * scale - (ftoutline.points[l].y - ftoutline.points[m].y) * scale / 3.0f;
							bezt->h2 = HD_VECT;
						}
					}

					/* get the handles that are aligned, tricky...
					 * dist_to_line_v2, check if the three beztriple points are on one line
					 * len_squared_v2v2, see if there's a distance between the three points
					 * len_squared_v2v2 again, to check the angle between the handles
					 * finally, check if one of them is a vector handle */
					if ((bezt->h1 != HD_VECT && bezt->h2 != HD_VECT) &&
					    (dist_to_line_v2(bezt->vec[0], bezt->vec[1], bezt->vec[2]) < 0.001f) &&
					    (len_squared_v2v2(bezt->vec[0], bezt->vec[1]) > 0.0001f * 0.0001f) &&
					    (len_squared_v2v2(bezt->vec[1], bezt->vec[2]) > 0.0001f * 0.0001f) &&
					    (len_squared_v2v2(bezt->vec[0], bezt->vec[2]) > 0.0002f * 0.0001f) &&
					    (len_squared_v2v2(bezt->vec[0], bezt->vec[2]) >
					     max_ff(len_squared_v2v2(bezt->vec[0], bezt->vec[1]),
					          len_squared_v2v2(bezt->vec[1], bezt->vec[2]))))
					{
						bezt->h1 = bezt->h2 = HD_ALIGN;
					}
					bezt->radius = 1.0f;
					bezt++;
				}
			}
		}
		if (npoints) MEM_freeN(npoints);
		if (onpoints) MEM_freeN(onpoints);
	}
}