msym_error_t findPermutation(msym_symmetry_operation_t *sop, int l, double (*v[l])[3], msym_thresholds_t *t, msym_permutation_t *perm){ msym_error_t ret = MSYM_SUCCESS; double m[3][3]; symmetryOperationMatrix(sop, m); perm->p = malloc(sizeof(int[l])); memset(perm->p, -1, sizeof(int[l])); //TODO: 2s complement perm->p_length = l; for(int i = 0; i < l;i++){ int j; double r[3]; mvmul(*v[i], m, r); for(j = 0;j < l;j++){ if(vequal(r, *v[j],t->permutation)){ perm->p[i] = j; break; } } if(j == l) { char buf[16]; symmetryOperationName(sop, sizeof(buf), buf); msymSetErrorDetails("Unable to determine permutation for symmetry operation %s",buf); ret = MSYM_PERMUTATION_ERROR; goto err; } } if(MSYM_SUCCESS != (ret = setPermutationCycles(perm))) goto err; return ret; err: free(perm->p); return ret; }
void gsrc_mousemove(int x, int y) { float axis[3], angle; vassign( v1, 2.0*x/glutGet(GLUT_WINDOW_WIDTH)-1, -2.0*y/glutGet(GLUT_WINDOW_HEIGHT)+1, 1 ); normalize(v1); if( vequal(v0,v1) ) return; cross(axis,v0,v1); normalize(axis); angle = acosf( clamp(dot(v0,v1),-1,1) ); vassign( v0, v1 ); glPushMatrix(); glLoadIdentity(); glRotatef( angle*180/PI, axis[0], axis[1], axis[2] ); // glTranslatef (axis[0], axis[1], axis[2]); //glScalef(1,1,1); //glTranslatef(-0.25, 0.5, 0.25); //glRotatef(3, axis[0], axis[1], axis[2]); //glScalef(1, 2, 1); glMultMatrixf( mo ); glGetFloatv( GL_MODELVIEW_MATRIX, mo ); glPopMatrix(); glutPostRedisplay(); }
static bool intersectSegCountour(const int* d0, const int* d1, int i, int n, const int* verts) { // For each edge (k,k+1) of P for (int k = 0; k < n; k++) { int k1 = next(k, n); // Skip edges incident to i. if (i == k || i == k1) continue; const int* p0 = &verts[k * 4]; const int* p1 = &verts[k1 * 4]; if (vequal(d0, p0) || vequal(d1, p0) || vequal(d0, p1) || vequal(d1, p1)) continue; if (intersect(d0, d1, p0, p1)) return true; } return false; }
// Returns T iff (v_i, v_j) is a proper internal *or* external // diagonal of P, *ignoring edges incident to v_i and v_j*. static bool diagonalie(int i, int j, int n, const int* verts, int* indices) { const int* d0 = &verts[(indices[i] & 0x0fffffff) * 4]; const int* d1 = &verts[(indices[j] & 0x0fffffff) * 4]; // For each edge (k,k+1) of P for (int k = 0; k < n; k++) { int k1 = next(k, n); // Skip edges incident to i or j if (!((k == i) || (k1 == i) || (k == j) || (k1 == j))) { const int* p0 = &verts[(indices[k] & 0x0fffffff) * 4]; const int* p1 = &verts[(indices[k1] & 0x0fffffff) * 4]; if (vequal(d0, p0) || vequal(d1, p0) || vequal(d0, p1) || vequal(d1, p1)) continue; if (intersect(d0, d1, p0, p1)) return false; } } return true; }
static void removeDegenerateSegments(rcIntArray& simplified) { // Remove adjacent vertices which are equal on xz-plane, // or else the triangulator will get confused. int npts = simplified.size()/4; for (int i = 0; i < npts; ++i) { int ni = next(i, npts); if (vequal(&simplified[i*4], &simplified[ni*4])) { // Degenerate segment, remove. for (int j = i; j < simplified.size()/4-1; ++j) { simplified[j*4+0] = simplified[(j+1)*4+0]; simplified[j*4+1] = simplified[(j+1)*4+1]; simplified[j*4+2] = simplified[(j+1)*4+2]; simplified[j*4+3] = simplified[(j+1)*4+3]; } simplified.resize(simplified.size()-4); npts--; } } }
//TODO: Use a preallocated pointer array instead of multiple mallocs msym_error_t generateEquivalenceSet(msym_point_group_t *pg, int length, msym_element_t elements[length], int *glength, msym_element_t **gelements, int *esl, msym_equivalence_set_t **es,msym_thresholds_t *thresholds){ msym_error_t ret = MSYM_SUCCESS; msym_element_t *ge = calloc(length,sizeof(msym_element_t[pg->order])); msym_equivalence_set_t *ges = calloc(length,sizeof(msym_equivalence_set_t)); int gel = 0; int gesl = 0; for(int i = 0;i < length;i++){ msym_equivalence_set_t *aes = NULL; int f; for(f = 0;f < gel;f++){ if(ge[f].n == elements[i].n && ge[f].m == elements[i].m && 0 == strncmp(ge[f].name, elements[i].name, sizeof(ge[f].name)) && vequal(ge[f].v, elements[i].v, thresholds->permutation)){ break; } } if(f == gel){ aes = &ges[gesl++]; aes->elements = calloc(pg->order,sizeof(msym_element_t*)); aes->length = 0; } else { continue; } if(elements[i].aol > 0 || elements[i].ao != NULL){ msymSetErrorDetails("Cannot (currently) generate equivalence sets from elements with orbitals"); ret = MSYM_INVALID_ELEMENTS; goto err; } for(msym_symmetry_operation_t *s = pg->sops;s < (pg->sops + pg->sopsl);s++){ double v[3]; applySymmetryOperation(s, elements[i].v, v); for(f = 0;f < gel;f++){ if(ge[f].n == elements[i].n && ge[f].m == elements[i].m && 0 == strncmp(ge[f].name, elements[i].name, sizeof(ge[f].name)) && vequal(ge[f].v, v, thresholds->permutation)){ break; } } if(f == gel){ memcpy(&ge[gel],&elements[i],sizeof(msym_element_t)); vcopy(v, ge[gel].v); aes->elements[aes->length++] = &ge[gel++]; } } if(pg->order % aes->length != 0){ msymSetErrorDetails("Equivalence set length (%d) not a divisor of point group order (%d)",pg->order); ret = MSYM_INVALID_EQUIVALENCE_SET; goto err; } aes->elements = realloc(aes->elements,sizeof(msym_element_t*[aes->length])); } msym_element_t *geo = ge; ge = realloc(ge,sizeof(msym_element_t[gel])); ges = realloc(ges,sizeof(msym_equivalence_set_t[gesl]) + sizeof(msym_element_t *[gel])); msym_element_t **ep = (msym_element_t **) &ges[gesl]; for(int i = 0;i < gesl;i++){ msym_element_t **tep = ep; for(int j = 0;j < ges[i].length;j++){ *ep = ges[i].elements[j] - geo + ge; ep++; } free(ges[i].elements); ges[i].elements = tep; } *glength = gel; *gelements = ge; *es = ges; *esl = gesl; return ret; err: free(ge); for(int i = 0; i < gesl;i++) free(ges[i].elements); free(ges); return ret; }
msym_error_t partitionPointGroupEquivalenceSets(msym_point_group_t *pg, int length, msym_element_t *elements[length], msym_element_t *pelements[length], int *esl, msym_equivalence_set_t **es, msym_thresholds_t *thresholds){ msym_error_t ret = MSYM_SUCCESS; msym_equivalence_set_t *ges = calloc(length,sizeof(msym_equivalence_set_t)); int *eqi = malloc(sizeof(int[length])); memset(eqi,-1,sizeof(int[length])); int gesl = 0, pelementsl = 0; for(int i = 0;i < length;i++){ if(eqi[i] >= 0) continue; if(pelementsl >= length){ msymSetErrorDetails("Size of equivalence sets (%d) larger than number of elements (%d)",pelementsl,length); ret = MSYM_INVALID_EQUIVALENCE_SET; goto err; } msym_equivalence_set_t *aes = &ges[gesl++]; aes->elements = &pelements[pelementsl]; for(msym_symmetry_operation_t *s = pg->sops;s < (pg->sops + pg->sopsl);s++){ double v[3]; int f; applySymmetryOperation(s, elements[i]->v, v); for(f = 0;f < length;f++){ if(elements[f]->n == elements[i]->n && elements[f]->m == elements[i]->m && 0 == strncmp(elements[f]->name, elements[i]->name, sizeof(elements[f]->name)) && vequal(elements[f]->v, v, thresholds->permutation)){ break; } } if(f < length && eqi[f] >= 0 && eqi[f] != gesl-1){ char buf[64]; symmetryOperationName(s, 64, buf); msymSetErrorDetails("Symmetry operation %s on element %d yeilded element (%d) in two diffenrent equivalence sets (%d and %d)",buf,i,f,eqi[f],gesl-1); ret = MSYM_INVALID_EQUIVALENCE_SET; goto err; } else if(f < length && eqi[f] == gesl-1){ //printf("element[%d] %s belongs to equivalence set %d, but already added\n",f,elements[f]->name, eqi[f]); } else if(f < length){ eqi[f] = gesl - 1; aes->elements[aes->length++] = elements[f]; //printf("element[%d] %s belongs to equivalence set %d, adding\n",f,elements[f]->name, eqi[f]); } else { char buf[64]; symmetryOperationName(s, 64, buf); msymSetErrorDetails("Cannot find permutation for %s when determining equivalence set from point group %s",buf,pg->name); ret = MSYM_INVALID_EQUIVALENCE_SET; goto err; } } //printf("generated equivalance set %d of length %d\n",gesl-1,aes->length); pelementsl += aes->length; } if(pelementsl != length){ msymSetErrorDetails("Size of equivalence sets (%d) is not equal to number of elements (%d)",pelementsl,length); ret = MSYM_INVALID_EQUIVALENCE_SET; goto err; } *es = ges; *esl = gesl; free(eqi); return ret; err: free(eqi); free(ges); return ret; }