// reduces a polynomial with respect to a set of polynomials F Polynomial *normal_form(Polynomial **set, Polynomial *orig, int index, int num_polys, int *reduced){ Polynomial *res, *temp; // we must try all quotient and remainders Polynomial **quots = (Polynomial **) malloc(sizeof(Polynomial *) * num_polys); Polynomial **rems = (Polynomial **) malloc(sizeof(Polynomial *) * num_polys); res = copy_poly(orig); *reduced = 0; printf("computing some reduction\n"); // try to divide using all things in the set for (int i = 0; i < num_polys; i++){ if (i == index) continue; divide_polys(orig, set[i], &(quots[i]), &(rems[i])); } printf("wtf tried to divide everything\n"); // nothing divided out completely the first time // keep trying to divide out stuff recursively for (int i = 0; i < num_polys; i++){ if (i == index) continue; // remainder is 0, return this right away if (rems[i]->terms[0].coeff.num == 0){ free(res); res = copy_poly(rems[i]); break; } // try to divide recursively else if (quots[i]->terms[0].coeff.num != 0){ temp = normal_form(set, rems[i], index, num_polys, reduced); free(res); // it reduced all the way if (temp->terms[0].coeff.num == 0){ res = copy_poly(temp); break; } else{ res = copy_poly(rems[i]); } free(temp); } } // free all this stuff for (int i = 0; i < num_polys; i++) { if (i == index) continue; free(quots[i]); free(rems[i]); } free(quots); free(rems); return res; }
void CReedSolomon::Modified_Berlekamp_Massey (void) { int L, L2, k, d; int psi [MAX_LENGTH], psi2 [MAX_LENGTH], D [MAX_LENGTH]; int gamma [MAX_LENGTH]; int iMaxLength = m_iCorrectCodeSize * 2; /* initialize Gamma, the erasure locator polynomial */ init_gamma (gamma); /* initialize to z */ copy_poly (D, gamma); mul_z_poly (D); copy_poly (psi, gamma); k = -1; L = m_NErasures; for (int n = m_NErasures; n < m_iCorrectCodeSize; n ++) { d = compute_discrepancy (psi, m_synBytes, L, n); if (d != 0) { /* psi2 = psi - d*D */ for (int i = 0; i < iMaxLength; i++) { psi2 [i] = psi [i] ^ gmult (d, D [i]); } if (L < (n - k)) { L2 = n - k; k = n - L; /* D = scale_poly(ginv(d), psi); */ for (int i = 0; i < iMaxLength; i ++) { D [i] = gmult (psi [i], ginv (d)); } L = L2; } /* psi = psi2 */ for (int i = 0; i < iMaxLength; i ++) { psi [i] = psi2 [i]; } } mul_z_poly (D); } for (int i = 0; i < MAX_LENGTH; i ++) { m_Lambda [i] = psi [i]; } compute_modified_omega (); }
/* From Cain, Clark, "Error-Correction Coding For Digital Communications", pp. 216. */ void Modified_Berlekamp_Massey (void) { int n, L, L2, k, d, i; int psi[MAXDEG], psi2[MAXDEG], D[MAXDEG]; int gamma[MAXDEG]; /* initialize Gamma, the erasure locator polynomial */ init_gamma(gamma); /* initialize to z */ copy_poly(D, gamma); mul_z_poly(D); copy_poly(psi, gamma); k = -1; L = NErasures; for (n = NErasures; n < NPAR; n++) { d = compute_discrepancy(psi, synBytes, L, n); if (d != 0) { /* psi2 = psi - d*D */ for (i = 0; i < MAXDEG; i++) psi2[i] = psi[i] ^ gmult(d, D[i]); if (L < (n-k)) { L2 = n-k; k = n-L; /* D = scale_poly(ginv(d), psi); */ for (i = 0; i < MAXDEG; i++) D[i] = gmult(psi[i], ginv(d)); L = L2; } /* psi = psi2 */ for (i = 0; i < MAXDEG; i++) psi[i] = psi2[i]; } mul_z_poly(D); } for(i = 0; i < MAXDEG; i++) Lambda[i] = psi[i]; compute_modified_omega(); }
Polynomial add_polys(Polynomial poly1, Polynomial poly2) { Polynomial poly = copy_poly(poly1); Monomial *current = poly2; while (current) { add_monom_to_poly(current->coeff, current->degree, &poly); current = current->next_monomial; } return poly; }
Polynomial divide_polys(Polynomial poly1, Polynomial poly2) { Polynomial tmp = copy_poly(poly1); Polynomial quotient = NULL; while (tmp) { double coeff = (double)tmp->coeff / poly2->coeff; int degree = tmp->degree - poly2->degree; if (coeff != (int)coeff || degree < 0) return NULL; Polynomial poly2_copy = copy_poly(poly2); multiply_monom_to_poly(-(int)coeff, degree, poly2_copy); Polynomial sum = add_polys(tmp, poly2_copy); free_poly(poly2_copy); free_poly(tmp); tmp = sum; add_monom_to_poly((int)coeff, degree, "ient); } free_poly(tmp); return quotient; return NULL; }
Polynomial multiply_polys(Polynomial poly1, Polynomial poly2) { Polynomial product = NULL; if (!poly1 || !poly2) return product; Monomial *current = poly2; while (current) { Polynomial poly = copy_poly(poly1); multiply_monom_to_poly(current->coeff, current->degree, poly); current = current->next_monomial; if (!product) product = copy_poly(poly); else { Polynomial sum = add_polys(product, poly); free_poly(product); product = sum; } free_poly(poly); } return product; }
/* gamma = product (1-z*a^Ij) for erasure locs Ij */ void CReedSolomon::init_gamma (int gamma []) { int tmp [MAX_LENGTH]; for (int i = 0; i < MAX_LENGTH; i ++) { gamma [i] = 0; tmp [i] = 0; } gamma[0] = 1; for (int e = 0; e < m_NErasures; e ++) { copy_poly (tmp, gamma); scale_poly (byExpToInt [m_ErasureLocs [e]], tmp); mul_z_poly (tmp); add_polys (gamma, tmp); } }
/* gamma = product (1-z*a^Ij) for erasure locs Ij */ void init_gamma (int gamma[]) { int e, tmp[MAXDEG]; zero_poly(gamma); zero_poly(tmp); gamma[0] = 1; for (e = 0; e < NErasures; e++) { copy_poly(tmp, gamma); scale_poly(gexp[ErasureLocs[e]], tmp); mul_z_poly(tmp); add_polys(gamma, tmp); } }
static void compute_genpoly (int nbytes, unsigned short genpoly[]) { unsigned short i, tp[256], tp1[256]; zero_poly(tp1); tp1[0] = 1; for (i = 1; i <= nbytes; i++) { zero_poly(tp); tp[0] = gexp[i]; /* set up x+a^n */ tp[1] = 1; mult_polys(genpoly, tp, tp1); copy_poly(tp1, genpoly); } }
static void compute_genpoly (int nbytes, int genpoly[]) { int i, tp[256], tp1[256]; /* multiply (x + a^n) for n = 1 to nbytes */ zero_poly(tp1); tp1[0] = 1; for (i = 1; i <= nbytes; i++) { zero_poly(tp); tp[0] = gexp[i]; /* set up x+a^n */ tp[1] = 1; mult_polys(genpoly, tp, tp1); copy_poly(tp1, genpoly); } }
// Create a generator polynomial for an n byte RS code. void init_genpoly_cache(int par) { int i; unsigned char tp[256], tp1[256]; int tmp; unsigned char *genpoly = genpoly_cache[par-1]; //multiply (x + a^n) for n = 1 to nbytes zero_poly(tp1, par*2); tp1[0] = 1; for (i = 1; i <= par; i++) { zero_poly(tp, par*2); tp[0] = gexp[i]; // set up x+a^n tp[1] = 1; mult_polys(genpoly, tp, tp1, par*2); copy_poly(tp1, genpoly, par*2); } for(i=0; i<par/2; i++) { tmp = genpoly[i] ; genpoly[i] = genpoly[par-1-i]; genpoly[par-1-i]=tmp; } for(i=0; i<256; i++) { for(int j=0; j<23; j++) genpoly_23_mult_cache[i][j] = gmult(i, genpoly_cache[22][j]); genpoly_23_mult_cache[i][23] = 0; } }
// does polynomial long division, p1 divided by p2 void divide_polys(Polynomial *p1, Polynomial *p2, Polynomial **quot, Polynomial **rem) { int max = 2 * p2->num_terms; int count = 0; Polynomial *res; Polynomial *old_temp, *new_temp; Polynomial *old_div, *new_div; Polynomial **quots; // need to allocate some polynomails, let's just assume we need // double the space of the dividend and then adjust if it goes over *quot = empty_poly(p1->num_vars, 1, p1->vars); divide_terms(&p1->terms[0], &p2->terms[0], &((*quot)->terms[0]), p1->num_vars); // not divisible from the get go, so the quot is 0 // and the remainder is all of p1 if ((*quot)->terms[0].coeff.num == 0) { *rem = copy_poly(p1); return; } // the first term was not 0, so we need to set this polynomial in our list of // partial quotients. don't forget to malloc space for the list quots = (Polynomial **) malloc(sizeof(Polynomial *) * max); quots[count] = *quot; count++; // copy the divisor old_div = copy_poly(p1); while(true) { res = multiply_polys(quots[count-1], p2); // get the new dividend new_div = subtract_polys(old_div, res); sort_polynomial(new_div); free(old_div); // see if it can be divided quots[count] = empty_poly(p1->num_vars, 1, p1->vars); divide_terms(&new_div->terms[0], &p2->terms[0], "s[count]->terms[0], p1->num_vars); if (quots[count]->terms[0].coeff.num == 0) { res = new_div; break; } // it divided, time to loop again count += 1; free(res); old_div = new_div; // increase solutions array ? if (count == max-1){ quots = double_poly_array(quots, &max); } } // sum everything in the quotes list old_temp = zero_poly(p1); for (int i = 0; i < count; i++) { new_temp = add_polys(old_temp, quots[i]); free(old_temp); free(quots[i]); old_temp = new_temp; } free(quots); // set the quotient and remainder *quot = new_temp; *rem = res; }
int pixel_loop(int pix, int n, polygon *input[/*n*/], int out_max, polygon *output[/*out_max*/]){ int *child_pix,children; int i,j,k,m,out,nout; int ier, iprune, np; polygon *pixel; polygon **poly; //allocate memory for work array of polygon pointers poly=(polygon **) malloc(sizeof(polygon *) * n); if(!poly){ fprintf(stderr, "pixel_loop: failed to allocate memory for %d polygon pointers\n",n); return(-1); } // allocate memory for child_pix array if(pix==0 && scheme=='d'){ child_pix=(int *) malloc(sizeof(int) * 117); children=117; if(!child_pix){ fprintf(stderr, "pixel_loop: failed to allocate memory for 117 integers\n"); return(-1); } } else{ child_pix=(int *) malloc(sizeof(int) * 4); children=4; if(!child_pix){ fprintf(stderr, "pixel_loop: failed to allocate memory for %d integers\n", 4); return(-1); } } get_child_pixels(pix, child_pix, scheme); out=0; for(i=0;i<children;i++){ /*get the current child pixel*/ pixel=get_pixel(child_pix[i], scheme); if(!pixel){ fprintf(stderr, "error in pixel_loop: could not get pixel %d\n", child_pix[i]); return(-1); } /*loop through input polygons to find the ones that overlap with current child pixel*/ for(j=0;j<n;j++){ /* skip null polygons */ if (input[j]->np > 0 && input[j]->cm[0] == 0.){ poly[j] = 0x0; continue; } np=input[j]->np+pixel->np; poly[j]=new_poly(np); if(!poly[j]){ fprintf(stderr, "error in pixel_loop: failed to allocate memory for polygon of %d caps\n", np); return(-1); } /*set poly[j] to the intersection of input[j] and current child pixel*/ poly_poly(input[j],pixel,poly[j]); poly[j]->pixel=pixel->pixel; iprune = prune_poly(poly[j], mtol); if (iprune == -1) { fprintf(stderr, "pixelize: failed to prune polygon for pixel %d; continuing ...\n", poly[j]->pixel); //return(-1); } /*if polygon is null, get rid of it*/ if (iprune >= 2) { free_poly(poly[j]); poly[j] = 0x0; } } /*copy down non-null polygons*/ k=0; for(j=0;j<n;j++){ if(poly[j]){ poly[k++]=poly[j]; } } m=k; /*nullify the rest of the array, but don't free, since pointers have been copied above*/ for(j=m;j<n;j++){ poly[j]=0x0; } /*if we're below the max resolution, recursively call pixel_loop on the current child pixel */ if(m>polys_per_pixel && get_res(child_pix[i],scheme)<res_max){ //printf("calling pixel loop for pixel %d with %d polygons\n",child_pix[i],m); nout=pixel_loop(child_pix[i],m,poly,out_max-out,&output[out]); if(nout==-1) return(-1); out+=nout; } else{ for(k=0;k<m;k++){ /* check whether exceeded maximum number of polygons */ if (out >= out_max) { fprintf(stderr, "pixel_loop: total number of polygons exceeded maximum %d\n", NPOLYSMAX); fprintf(stderr, "if you need more space, enlarge NPOLYSMAX in defines.h, and recompile\n"); return(-1); } /*make sure output polygon has enough room */ ier = room_poly(&output[out], poly[k]->np, DNP, 0); if (ier == -1) { fprintf(stderr, "error in pixel_loop: failed to allocate memory for polygon of %d caps\n", poly[i]->np + DNP); return(-1); } /*copy polygon to output array*/ copy_poly(poly[k],output[out]); out++; } } /*free up memory for next child pixel*/ free_poly(pixel); for(j=0;j<n;j++){ free_poly(poly[j]); } } free(child_pix); free(poly); return out; }
/*------------------------------------------------------------------------------ If poly1 overlaps poly2, split poly1 into two parts. If poly3 is null on input, then the appropriate return value is returned, but poly1 is not actually split. Input: *poly1, poly2 are 2 polygons. mtol = initial angular tolerance within which to merge multiple intersections. Output: If **poly3 is not null on input, then: *poly1 and *poly3 are 2 split polygons of poly1, if poly1 is split, with *poly1 the part outside poly2, and *poly3 the part intersecting poly2; *poly1 and *poly3 remain untouched if poly1 is not split. If **poly3 is null on input, then *poly1 remains untouched. Return value: -1 = error occurred; 0 = poly1 and poly2 have zero intersection; 1 = poly2 fully encloses poly1; 2 = poly2 splits poly1 into two. */ int split_poly(polygon **poly1, polygon *poly2, polygon **poly3, double mtol, char bmethod) { static polygon *poly = 0x0, *poly4 = 0x0; int ier, ip, iprune, np, np1, verb; double area, area_tot, cm, tol; /* poly2 is whole sphere, therefore contains poly1 */ if (poly2->np == 0){ /* set weight according to balkanization scheme: */ if(bmethod=='l'){ //do nothing - this is the default behavior } else if(bmethod=='a'){ (*poly1)->weight=(*poly1)->weight + poly2->weight; } else if(bmethod=='n'){ (*poly1)->weight=((*poly1)->weight > poly2->weight)? poly2->weight : (*poly1)->weight ; } else if(bmethod=='x'){ (*poly1)->weight=((*poly1)->weight > poly2->weight)? (*poly1)->weight : poly2->weight ; } else{ fprintf(stderr, "error in split_poly: balkanize method %c not recognized.\n", bmethod); return(-1); } return(1); } /* make sure poly contains enough space for intersection */ np = (*poly1)->np + poly2->np; ier = room_poly(&poly, np, DNP, 0); if (ier == -1) goto out_of_memory; /* intersection of poly1 and poly2 */ poly_poly(*poly1, poly2, poly); /* suppress coincident boundaries, to make garea happy */ iprune = trim_poly(poly); /* intersection of poly1 and poly2 is null polygon */ if (iprune >= 2) return(0); /* area of intersection */ tol = mtol; verb = 1; ier = garea(poly, &tol, verb, &area_tot); if (ier) goto error; /* poly1 and poly2 have zero intersection */ if (area_tot == 0.) return(0); /* number of caps of poly1 */ np1 = (*poly1)->np; /* find boundary of poly2 which intersects poly1 */ verb = 0; for (ip = 0; ip < poly2->np; ip++) { cm = poly->cm[np1 + ip]; poly->cm[np1 + ip] = 2.; /* suppress boundary to be tested */ tol = mtol; ier = garea(poly, &tol, verb, &area); /* area of intersection sans boundary */ poly->cm[np1 + ip] = cm; /* restore tested boundary */ if (area > area_tot) { /* boundary intersects poly1 */ /* poly2 splits poly1, but do not actually split */ if (!poly3) return(2); /* number of caps of poly1 with extra boundary */ np = np1 + 1; /* make sure poly3 contains enough space */ ier = room_poly(poly3, np, DNP, 0); if (ier == -1) goto out_of_memory; /* poly3 is intersection of poly1 and ip'th cap of poly2 */ poly_polyn(*poly1, poly2, ip, 1, *poly3); /* prune poly3 */ iprune = prune_poly(*poly3, mtol); if (iprune == -1) goto error; /* poly3 may be null because of roundoff: skip to next cap */ if (iprune >= 2) continue; /* make sure poly4 contains enough space */ ier = room_poly(&poly4, np, DNP, 1); if (ier == -1) goto out_of_memory; /* poly4 is intersection of poly1 and complement of ip'th cap of poly2 */ poly_polyn(*poly1, poly2, ip, -1, poly4); /* prune poly4 */ iprune = prune_poly(poly4, mtol); if (iprune == -1) goto error; /* poly4 may be null because of roundoff: skip to next cap */ if (iprune >= 2) continue; /* make sure poly1 contains enough space */ np = poly4->np; ier = room_poly(poly1, np, DNP, 0); if (ier == -1) goto out_of_memory; /* copy poly4 into poly1 */ copy_poly(poly4, *poly1); /* poly1 successfully split into poly1 and poly3 */ /* set weight according to balkanization scheme: */ if(bmethod=='l'){ //do nothing - this is the default behavior } else if(bmethod=='a'){ (*poly3)->weight=(*poly1)->weight + poly2->weight; } else if(bmethod=='n'){ (*poly3)->weight=((*poly1)->weight > poly2->weight)? poly2->weight : (*poly1)->weight ; } else if(bmethod=='x'){ (*poly3)->weight=((*poly1)->weight > poly2->weight)? (*poly1)->weight : poly2->weight ; } else{ fprintf(stderr, "error in split_poly: balkanize method %c not recognized.\n", bmethod); return(-1); } return(2); } else if (area < area_tot) { /* area should be >= area_tot because suppressing a boundary of poly should always increase its area; but this can happen because of roundoff */ //fprintf(stderr, "split_poly: area %.16g of polygon with boundary %d suppressed should be >= area %.16g of polygon\n", area, ip, area_tot); } } /* poly2 contains poly1 */ /* set weight according to balkanization scheme: */ if(bmethod=='l'){ //do nothing - this is the default behavior } else if(bmethod=='a'){ (*poly1)->weight=(*poly1)->weight + poly2->weight; } else if(bmethod=='n'){ (*poly1)->weight=((*poly1)->weight > poly2->weight)? poly2->weight : (*poly1)->weight ; } else if(bmethod=='x'){ (*poly1)->weight=((*poly1)->weight > poly2->weight)? (*poly1)->weight : poly2->weight ; } else{ fprintf(stderr, "error in split_poly: balkanize method %c not recognized.\n", bmethod); return(-1); } return(1); /* ---------------- error returns ---------------- */ error: return(-1); out_of_memory: fprintf(stderr, "split_poly: failed to allocate memory for polygon of %d caps\n", np + DNP); return(-1); }
/*------------------------------------------------------------------------------ Balkanize overlapping polygons into many disjoint connected polygons. Input: npoly = number of polygons. poly = array of pointers to polygons. npolys = maximum number of output polygons. mtol = tolerance angle for multiple intersections. fmt = pointer to format structure. axtol, btol, thtol, ytol = tolerance angles (see documentation). Output: polys = array of pointers to polygons. Return value: number of disjoint connected polygons, or -1 if error occurred. */ int balkanize(int npoly, polygon *poly[/*npoly*/], int npolys, polygon *polys[/*npolys*/], long double mtol, format *fmt, long double axtol, long double btol, long double thtol, long double ytol) { /* part_poly should lasso one-boundary polygons only if they have too many caps */ #define ALL_ONEBOUNDARY 1 /* how part_poly should tighten lasso */ #define ADJUST_LASSO 1 /* part_poly should force polygon to be split even if no part can be lassoed */ #define FORCE_SPLIT 1 /* partition_poly should overwrite all original polygons */ #define OVERWRITE_ORIGINAL 2 #define WARNMAX 8 char *snapped_polys = 0x0; int discard, dm, dn, dnp, failed, i, ier, inull, isnap, ip, iprune, j, k, m, n, nadj, np, selfsnap; int *start; int *total; int begin, end, p, max_pixel; long double tol; poly_sort(npoly, poly, 'p'); /* allocate memory for pixel info arrays start and total */ max_pixel=poly[npoly-1]->pixel+1; start = (int *) malloc(sizeof(int) * max_pixel); if (!start) { fprintf(stderr, "balkanize: failed to allocate memory for %d integers\n", max_pixel); return(-1); } total = (int *) malloc(sizeof(int) * max_pixel); if (!total) { fprintf(stderr, "balkanize: failed to allocate memory for %d integers\n", max_pixel); return(-1); } /* build lists of starting indices of each pixel and total number of polygons in each pixel*/ ier=pixel_list(npoly, poly, max_pixel, start, total); if (ier == -1) { fprintf(stderr, "balkanize: error building pixel index lists\n"); return(-1); } /* start by pruning all input polygons */ np = 0; inull = 0; for (i = 0; i < npoly; i++) { tol = mtol; iprune = prune_poly(poly[i], tol); /* error */ if (iprune == -1) { fprintf(stderr, "balkanize: initial prune failed at polygon %d\n", poly[i]->id); return(-1); } /* zero area polygon */ if (iprune >= 2) { if (WARNMAX > 0 && inull == 0) msg("warning from balkanize: following polygons have zero area & are being discarded:\n"); if (inull < WARNMAX) { msg(" %lld", (fmt->newid == 'o')? poly[i]->id : (long long)i); } else if (inull == WARNMAX) { msg(" ... more\n"); } inull++; } else { np++; } } if (WARNMAX > 0 && inull > 0 && inull <= WARNMAX) msg("\n"); if (inull > 0) { msg("balkanize: %d polygons with zero area are being discarded;\n", inull); } /* number of polygons */ msg("balkanizing %d polygons ...\n", np); /* nullify all output polygons */ for (i = 0; i < npolys; i++) { polys[i] = 0x0; } /* m = starting index of current set of fragments of i'th polygon dm = number of current set of fragments of i'th polygon n = starting index of new subset of fragments of i'th polygon dn = number of new subset of fragments of i'th polygon */ msg("balkanize stage 1 (fragment into non-overlapping polygons):\n"); n = 0; dnp = 0; ip = 0; /* go through each pixel and fragment each polygon against the other polygons in its pixel */ for(p=0;p<max_pixel;p++){ begin=start[p]; end=start[p]+total[p]; /* too many polygons */ if (n >= npolys) break; /* fragment each polygon in turn */ for (i = begin; i < end; i++) { /* skip null polygons */ if (poly[i]->np > 0 && poly[i]->cm[0] == 0.) continue; /* update indices */ m = n; dm = 1; n = m + dm; /* make sure output polygon has enough room */ ier = room_poly(&polys[m], poly[i]->np, DNP, 0); if (ier == -1) { fprintf(stderr, "balkanize: failed to allocate memory for polygon of %d caps\n", poly[i]->np + DNP); return(-1); } /* copy polygon i into output polygon */ copy_poly(poly[i], polys[m]); /* fragment successively against other polygons */ for (j = begin; j < end; j++) { /* skip self, or null polygons */ if (j == i || (poly[j]->np > 0 && poly[j]->cm[0] == 0.)) continue; /* keep only one copy of the intersection of i & j */ /* intersection inherits weight of polygon being fragmented, so keeping later polygon ensures intersection inherits weight of later polygon */ if (i < j) { discard = 1; } else { discard = 0; } /* fragment each part of i'th polygon */ for (k = m; k < m + dm; k++) { /* skip null polygons */ if (!polys[k] || (polys[k]->np > 0 && polys[k]->cm[0] == 0.)) continue; /* fragment */ tol = mtol; dn = fragment_poly(&polys[k], poly[j], discard, npolys - n, &polys[n], tol, bmethod); /* error */ if (dn == -1) { fprintf(stderr, "balkanize: UHOH at polygon %lld; continuing ...\n", (fmt->newid == 'o')? polys[i]->id : (long long)ip); continue; /* return(-1); */ } /* increment index of next subset of fragments */ n += dn; /* increment polygon count */ np += dn; dnp += dn; if (!polys[k]) { np--; dnp--; } /* check whether exceeded maximum number of polygons */ //printf("(1) n = %d\n", n); if (n > npolys) { fprintf(stderr, "(1) balkanize: total number of polygons (= %d) exceeded maximum %d\n", npoly + n, npoly + npolys); fprintf(stderr, "if you need more space, enlarge NPOLYSMAX in defines.h, and recompile\n"); fprintf(stderr, "currently, dn = %d, np = %d, dnp = %d, poly[%d]->id = %lld, poly[%d]->pixel = %d\n", dn, np, dnp, i, poly[i]->id, i, poly[i]->pixel); n = npolys; #ifdef CARRY_ON_REGARDLESS break; #else return(-1); #endif } } /* copy down non-null polygons */ dm = 0; for (k = m; k < n; k++) { if (polys[k]) { polys[m + dm] = polys[k]; dm++; } } /* nullify but don't free, because freeing polys[k] will free polys[m + dm] */ for (k = m + dm; k < n; k++) { polys[k] = 0x0; } n = m + dm; if (dm == 0) break; } /* too many polygons */ if (n >= npolys) break; ip++; } } free(start); free(total); msg("added %d polygons to make %d\n", dnp, np); // partition disconnected polygons into connected parts msg("balkanize stage 2 (partition disconnected polygons into connected parts):\n"); m = n; dnp = 0; ip = 0; failed = 0; for (i = 0; i < m; i++) { // skip null polygons if (!polys[i] || (polys[i]->np > 0 && polys[i]->cm[0] == 0.)) continue; // partition disconnected polygons tol = mtol; ier = partition_poly(&polys[i], npolys - n, &polys[n], tol, ALL_ONEBOUNDARY, ADJUST_LASSO, FORCE_SPLIT, OVERWRITE_ORIGINAL, &dn); // error if (ier == -1) { fprintf(stderr, "balkanize: UHOH at polygon %lld; continuing ...\n", (fmt->newid == 'o')? polys[i]->id : (long long)ip); continue; // return(-1); // failed to partition polygon into desired number of parts } else if (ier == 1) { fprintf(stderr, "balkanize: failed to partition polygon %lld fully; partitioned it into %d parts\n", (fmt->newid == 'o')? polys[i]->id : (long long)ip, dn + 1); failed++; } // increment index of next subset of fragments n += dn; // increment polygon count np += dn; dnp += dn; // check whether exceeded maximum number of polygons //printf("(2) n = %d\n", n); if (n > npolys) { fprintf(stderr, "(2) balkanize: total number of polygons (= %d) exceeded maximum %d\n", n + npoly, npoly + npolys); fprintf(stderr, "if you need more space, enlarge NPOLYSMAX in defines.h, and recompile\n"); n = npolys; #ifdef CARRY_ON_REGARDLESS break; #else return(-1); #endif } ip++; } msg("added %d polygons to make %d\n", dnp, np); if (failed > 0) { msg("balkanize: failed to split %d polygons into desired number of connected parts\n", failed); msg(".............................................................................\n"); msg("Failure to split polygon probably means:\n"); msg("either (1) you forgot to run snap on all your input polygon files;\n"); msg(" or (2) the polygon is too small for the numerics to cope with;\n"); msg(" or (3) you have a weird-shaped polygon.\n"); msg("You may ignore this warning message if the weights of polygons in the input\n"); msg("polygon file(s) are already correct, and you do not want to reweight them.\n"); msg("Similarly, you may ignore this warning message if you do want to reweight the\n"); msg("polygons, but the weights of the different parts of each unsplit polygon are\n"); msg("the same. If you want to reweight the different parts of an unsplit polygon\n"); msg("with different weights, then you will need to split that polygon by hand.\n"); msg("Whatever the case, the output file of balkanized polygons constitutes\n"); msg("a valid mask of non-overlapping polygons, which is safe to use.\n"); msg(".............................................................................\n"); } /* prune */ j = 0; inull = 0; for (i = 0; i < n; i++) { tol = mtol; iprune = prune_poly(polys[i], tol); if (iprune == -1) { fprintf(stderr, "balkanize: failed to prune polygon %lld; continuing ...\n", (fmt->newid == 'o')? polys[i]->id : (long long)j); /* return(-1); */ } if (iprune >= 2) { free_poly(polys[i]); polys[i] = 0x0; inull++; } else { polys[j] = polys[i]; j++; } } if (inull > 0) msg("balkanize: %d balkanized polygons have zero area, and are being discarded\n", inull); n = j; /* // allocate snapped_polys array snapped_polys = (char *) malloc(sizeof(char) * n); if (!snapped_polys) { fprintf(stderr, "balkanize: failed to allocate memory for %d characters\n", n); return(-1); } //snap edges of each polygon selfsnap = 1; nadj = snap_polys(fmt, n, polys, selfsnap, axtol, btol, thtol, ytol, mtol, WARNMAX, snapped_polys); if(nadj==-1){ msg("balkanize: error snapping balkanized polygons\n"); return(-1); } // number of polygons whose edges were snapped isnap = 0; for (i = 0; i < n; i++) if (snapped_polys[i]) isnap++; if (isnap > 0) msg("balkanize: edges of %d balkanized polygons were snapped\n", isnap); // prune snapped polygons j = 0; inull = 0; for (i = 0; i < n; i++) { if (snapped_polys[i]) { iprune = prune_poly(polys[i], mtol); if (iprune == -1) { fprintf(stderr, "balkanize: failed to prune polygon %lld; continuing ...\n", (fmt->newid == 'o')? polys[i]->id : (long long)j); // return(-1); } if (iprune >= 2) { free_poly(polys[i]); polys[i] = 0x0; inull++; } else { polys[j] = polys[i]; j++; } } else { polys[j] = polys[i]; j++; } } if (inull > 0) msg("balkanize: %d snapped polygons have zero area, and are being discarded\n", inull); n = j; // free snapped_polys array free(snapped_polys); */ if(n!=-1){ /* sort polygons by pixel number */ poly_sort(n, polys,'p'); msg("balkanize: balkans contain %d polygons\n", n); } /* assign new polygon id numbers in place of inherited ids */ if (fmt->newid == 'n') { for (i = 0; i < n; i++) { polys[i]->id = (long long)i; } } if (fmt->newid == 'p') { for (i = 0; i < n; i++) { polys[i]->id = (long long)polys[i]->pixel; } } return(n); }