// Adjust if the point lies in the triangle abc REAL InTriangle(MESH * pMesh, VERTEX2D * pVer, TRIANGLE * pTri) { int vertex_index; VERTEX2D * pV1, *pV2, *pV3; vertex_index =pTri->i1; pV1 = (VERTEX2D *)(pMesh->pVerArr+vertex_index); vertex_index =pTri->i2; pV2 = (VERTEX2D *)(pMesh->pVerArr+vertex_index); vertex_index =pTri->i3; pV3 = (VERTEX2D *)(pMesh->pVerArr+vertex_index); REAL ccw1 = CounterClockWise(pV1, pV2, pVer); REAL ccw2 = CounterClockWise(pV2, pV3, pVer); REAL ccw3 = CounterClockWise(pV3, pV1, pVer); REAL r = -1; if (ccw1>0 && ccw2>0 && ccw3>0) { r = 1; } else if(ccw1*ccw2*ccw3 == 0 && (ccw1*ccw2 > 0 || ccw1*ccw3 > 0 || ccw2*ccw3 > 0) ) { r = 0; } return r; }
bool IncrementalBlueNoise::InTriangle(Edge* edge, Node2d * target_node, int &mode) { // Node2d* new_node = target_node; Node2d* n1 = edge->getSourceNode(); Edge* e1 = edge; Edge* e2 = edge->getNextEdgeInFace(); Node2d* n2 = e2->getSourceNode(); Edge* e3 = e2->getNextEdgeInFace(); Node2d* n3 = e3->getSourceNode(); real ccw1 = CounterClockWise(n1, n2, target_node); // 如果target_node 在 1 2 的 右侧 则 顺时针, 负值 real ccw2 = CounterClockWise(n2, n3, target_node); // 如果target_node 在 2 3 的 左侧 则 逆时针, 正值 real ccw3 = CounterClockWise(n3, n1, target_node); if (ccw1 > 0 && ccw2 > 0 && ccw3 > 0) { mode = 0; return true; } else if (ccw1*ccw2*ccw3 == 0) { if (ccw2*ccw3 > 0) mode = 1; else if (ccw1*ccw3 > 0) mode = 2; else if (ccw1*ccw2 > 0) mode = 3; return true; } mode = -1; return false; }
// Create a new node and add it into triangle list TRIANGLE * AddTriangleNode(MESH * pMesh, TRIANGLE * pPrevTri, int i1, int i2, int i3) { // test if 3 vertices are co-linear if(CounterClockWise((VERTEX2D *)(pMesh->pVerArr+i1), (VERTEX2D *)(pMesh->pVerArr+i2), (VERTEX2D *)(pMesh->pVerArr+i3)) == 0) { return NULL; } // allocate memory TRIANGLE * pNewTestTri = (TRIANGLE *)malloc(sizeof(TRIANGLE)); pNewTestTri->i1 = i1; pNewTestTri->i2 = i2; pNewTestTri->i3 = i3; // insert after prev triangle if (pPrevTri == NULL) // add root { pMesh->pTriArr = pNewTestTri; pNewTestTri->pNext = NULL; pNewTestTri->pPrev = NULL; } else { pNewTestTri->pNext = pPrevTri->pNext; pNewTestTri->pPrev = pPrevTri; if(pPrevTri->pNext != NULL) { pPrevTri->pNext->pPrev = pNewTestTri; } pPrevTri->pNext = pNewTestTri; } return pNewTestTri; }
/* Reconstruct triangulation from indexed set of triangles. */ Triangulator::Triangulator(const vector<CParticleF>& pnts, const vector<_Internal::_indexed_triangle>& faces) { for(int i=0; i<pnts.size(); ++i) { points.push_back(new _Internal::_vertex(pnts[i])); } for(int i=0; i<faces.size(); ++i) { _Internal::_vertex* p[3]; for(int j=0; j<3; ++j) { p[j] = points[faces[i].index[j]]; } float ccw = CounterClockWise(p[0]->p, p[1]->p, p[2]->p); if(ccw > 0) { //arrange them in clockwise orientation swap(p[0], p[2]); } _Internal::_edge* e[3]; for(int j=0; j<3; ++j) { _Internal::_vertex* u = p[j]; _Internal::_vertex* v = p[(j+1)%3]; e[j] = new _Internal::_edge(u, v); vector<_Internal::_edge*>::iterator it = find_if(edges.begin(), edges.end(), _Internal::_edge_equal(e[j])); if(it==edges.end()) { edges.push_back(e[j]); } else { delete e[j]; e[j] = *it; } u->AddEdge(e[j]); v->AddEdge(e[j]); } _Internal::_triangle* tr = new _Internal::_triangle(e[0], e[1], e[2], p[0], p[1], p[2]); this->faces.push_back(tr); for(int j=0; j<3; ++j) { e[j]->AddFace(tr); } } for(int i=0; i<edges.size(); ++i) { if(edges[i]->faces[0]==NULL && edges[i]->faces[1]==NULL) { edges[i]->type = _Internal::Isolated; } else if(edges[i]->faces[0]!=NULL && edges[i]->faces[1]!=NULL) { edges[i]->type = _Internal::Inside; } else { edges[i]->type = _Internal::Boundary; //we do not consider Hole for now... } } }
int trichro_back_buffer(int xchroma, int ychroma, int rayon, int largeurchroma)//calcul et couleurs dans les 10eme de sec. { clear_bitmap(bmp_buffer_trichro); int coord[4]; for (hcl=0.0; hcl<360.0; hcl+=0.4) { xcl = cos(hcl*PI/180.0)*(rayon+16); ycl = sin(hcl*PI/180.0)*(rayon+16); hsv_to_rgb(hcl, 1.0, 1.0, &rcl, &gcl, &bcl); coord[0]=xchroma; coord[1]=ychroma; coord[2]=(int)(xchroma+xcl); coord[3]=(int)(ychroma+ycl); // Line(Vec2D(xchroma,ychroma),Vec2D(xchroma+xcl,ychroma+ycl)).Draw(Rgba(rcl,gcl,bcl)); polygon(bmp_buffer_trichro, 2, coord, makecol(rcl,gcl,bcl)); } //Circle MasqueNoir(Vec2D(xchroma,ychroma),rayon-16); //MasqueNoir.Draw(CouleurFond); circlefill(bmp_buffer_trichro, xchroma,ychroma, rayon-16, makecol(0,0,0)); for(angle = 0 ; angle <(PI*360) / 180 ; angle+=0.1)//radians { vx = cos(angle)*rayon; vy = sin(angle)*rayon; if(mouse_x>xtrichro_window+vx-16 && mouse_x< xtrichro_window+vx+16 && mouse_y>ytrichro_window+vy-16 && mouse_y<ytrichro_window+vy+16 && mouse_button==1 && window_focus_id==902) { angle_snap=angle;//angle rotation roue couleur position_curseur_hue_x= xtrichro_window+vx;//affichage position_curseur_hue_y=ytrichro_window+vy ;//affichage cref=getpixel(bmp_buffer_trichro,(int)(xchroma+vx),(int)(ychroma+vy)); r_pick=getr(cref); v_pick=getg(cref); b_pick=getb(cref); stock_etat_picker_dans_dockcolor(dock_color_selected); do_colors();//ventilation des niveaux pickés ainsi que distrib dans faders et docks midi_levels[497]=(int)(angle_snap/((PI*360) / (180*127))); if(midi_send_out[497]==1){index_send_midi_out[497]=1;} index_snap_color_wheel_levels=1; mouse_released=1; } } //attaque midi if (miditable[0][497]==istyp && miditable[1][497]==ischan && miditable[2][497]==ispitch) { angle_snap=((PI*360) / (180*127))*midi_levels[497]; vx = cos(angle_snap)*125; vy = sin(angle_snap)*125; position_curseur_hue_x= xtrichro_window+vx; position_curseur_hue_y=ytrichro_window+vy ; cref=getpixel(bmp_buffer_trichro,(int)(xchroma+vx),(int)(ychroma+vy)); r_pick=getr(cref); v_pick=getg(cref); b_pick=getb(cref); stock_etat_picker_dans_dockcolor(dock_color_selected); do_colors();//ventilation des niveaux pickés ainsi que distrib dans faders et docks if (midi_levels[497]!=previous_trichro_wheel) { index_snap_color_wheel_levels=1; previous_trichro_wheel=midi_levels[497]; } } //triangle V3D_f v1 = { xchroma+vxd, ychroma+vyd, 0, 0., 0., makecol(0, 0, 0) // black vertex }; V3D_f v2 = { xchroma+vxw, ychroma+vyw, 0, 0., 0., makecol(255, 255, 255) // white vertex }; V3D_f v3 = { xchroma+vxh, ychroma+vyh, 0, 0., 0., makecol(r_pick, v_pick, b_pick) // color vertex }; triangle3d_f(bmp_buffer_trichro, POLYTYPE_GCOL, NULL, &v1, &v2, &v3); //definir si on est dans l aire du triangle //(angle (Pa-1 Pa-2) * angle (Pa-2 Pa-3) * angle (Pa-3 Pa-1)) resultat pos ou neg float angle1, angle2,angle3; angle1=CounterClockWise(mouse_x,mouse_y,xtrichro_window+vxd, ytrichro_window+vyd,xtrichro_window+vxh, ytrichro_window+vyh) ; //Pa1-Pa2 angle2=CounterClockWise(mouse_x,mouse_y,xtrichro_window+vxh, ytrichro_window+vyh,xtrichro_window+vxw, ytrichro_window+vyw);//Pa2 - Pa3 angle3=CounterClockWise(mouse_x,mouse_y,xtrichro_window+vxw, ytrichro_window+vyw, xtrichro_window+vxd, ytrichro_window+vyd);//Pa3-Pa1 if((angle1*angle2*angle3) <=0 ) //dans le triangle formé par la souris et les 3 points du triangle { if(mouse_b&1 && mouse_x>xtrichro_window+vxd && mouse_x<xtrichro_window+vxw && mouse_y>ytrichro_window+vyd && mouse_y<ytrichro_window+vyh && window_focus_id==902) { picker_x=mouse_x-xtrichro_window; picker_y=mouse_y-ytrichro_window; stock_etat_picker_dans_dockcolor(dock_color_selected); do_colors();//ventilation des niveaux pickés ainsi que distrib dans faders et docks index_snap_color_wheel_levels=1; } } if( index_snap_color_wheel_levels==1)//take measurement on mouse or midi { if(getpixel(bmp_buffer_trichro,(int)(xchroma+picker_x),(int)(ychroma+picker_y))!=0) {colorpicker=getpixel(bmp_buffer_trichro,(int)(xchroma+picker_x),(int)(ychroma+picker_y));} my_red=getr(colorpicker); my_green=getg(colorpicker); my_blue=getb(colorpicker); if (index_quadri==1) { float hue, saturation, value; rgb_to_hsv(my_red, my_green, my_blue, &hue, &saturation, &value); //saturation: plus il y en a , moins de jaune il y a my_yellow=(int)(255-(255*saturation)); } do_colors();//ventilation des niveaux pickés ainsi que distrib dans faders et docks index_snap_color_wheel_levels=0; } return(0); }
bool FlipTest(MESH * pMesh, TRIANGLE * pTestTri) { bool flipped = false; int index_a = pTestTri->i1; int index_b = pTestTri->i2; int index_p = pTestTri->i3; int statify[3]={0,0,0}; int vertex_index; int* pi; int k = 1; // find the triangle which has edge consists of start and end TRIANGLE * pTri = pMesh->pTriArr; int index_d = -1; while (pTri != NULL) { statify[0] = 0; statify[1] = 0; statify[2] = 0; pi = &(pTri->i1); for (int j=0, k = 1; j<3; j++, k*= 2) { vertex_index = *pi++; if(vertex_index == index_a || vertex_index == index_b) { statify[j] = k; } } switch(statify[0] | statify[1] | statify[2] ) { case 3: if(CounterClockWise((VERTEX2D *)(pMesh->pVerArr+index_a), (VERTEX2D *)(pMesh->pVerArr+index_b), (VERTEX2D *)(pMesh->pVerArr+pTri->i3)) < 0) { index_d = pTri->i3; } break; case 5: if(CounterClockWise((VERTEX2D *)(pMesh->pVerArr+index_a), (VERTEX2D *)(pMesh->pVerArr+index_b), (VERTEX2D *)(pMesh->pVerArr+pTri->i2)) < 0) { index_d = pTri->i2; } break; case 6: if(CounterClockWise((VERTEX2D *)(pMesh->pVerArr+index_a), (VERTEX2D *)(pMesh->pVerArr+index_b), (VERTEX2D *)(pMesh->pVerArr+pTri->i1)) < 0) { index_d = pTri->i1; } break; default: break; } if (index_d != -1) { VERTEX2D * pa = (VERTEX2D *)(pMesh->pVerArr+index_a); VERTEX2D * pb = (VERTEX2D *)(pMesh->pVerArr+index_b); VERTEX2D * pd = (VERTEX2D *)(pMesh->pVerArr+index_d); VERTEX2D * pp = (VERTEX2D *)(pMesh->pVerArr+index_p); if(InCircle( pa, pb, pp, pd) < 0) // not local Delaunay { flipped = true; // add new triangle adp, dbp, remove abp, abd. // allocate memory for adp TRIANGLE * pT1 = AddTriangleNode(pMesh, pTestTri, pTestTri->i1, index_d, pTestTri->i3); // allocate memory for dbp TRIANGLE * pT2 = AddTriangleNode(pMesh, pT1, index_d, pTestTri->i2, index_p); // remove abp RemoveTriangleNode(pMesh, pTestTri); // remove abd RemoveTriangleNode(pMesh, pTri); FlipTest(pMesh, pT1); // pNewTestTri satisfies CCW order FlipTest(pMesh, pT2); // pNewTestTri2 satisfies CCW order break; } } // go to next item pTri = pTri->pNext; } return flipped; }
Triangulator::Triangulator(const vector<CParticleF>& pnts) { for(int i=0; i<pnts.size(); ++i) { points.push_back(new _Internal::_vertex(pnts[i])); } vector<TriangulateBourke::Triplet> delaunayTriangles = TriangulateBourke::DelaunayTriangulation(pnts); /*if(tripletSanityCheck(delaunayTriangles, pnts.size()) > 0) { int i=0; }*/ for(int i=0; i<delaunayTriangles.size(); i++) { int xk = delaunayTriangles[i].index[0]; int yk = delaunayTriangles[i].index[1]; int zk = delaunayTriangles[i].index[2]; assert(xk>=0 && xk<pnts.size() && yk>=0 && yk<pnts.size() && zk>=0 && zk<pnts.size()); CParticleF x = pnts[xk]; CParticleF y = pnts[yk]; CParticleF z = pnts[zk]; float ccw = CounterClockWise(x, y, z); if(ccw > 0) { //arrange them in clockwise orientation swap(xk, zk); swap(x, z); } _Internal::_edge* tedges[3]; tedges[0] = (new _Internal::_edge(points[xk], points[yk])); tedges[1] = (new _Internal::_edge(points[yk], points[zk])); tedges[2] = (new _Internal::_edge(points[zk], points[xk])); _Internal::_triangle* tr = new _Internal::_triangle(0, 0, 0, points[xk], points[yk], points[zk]); faces.push_back(tr); //add new edges to the edge vector. Make association with a new face and edges. for(int j=0; j<3; ++j) { vector<_Internal::_edge*>::iterator it = find_if(edges.begin(), edges.end(), _Internal::_edge_equal(tedges[j])); if(it == edges.end()) { edges.push_back(tedges[j]); } else { delete tedges[j]; tedges[j] = *it; } tr->edges[j] = tedges[j]; tedges[j]->AddFace(tr); } points[xk]->AddEdge(tedges[0]); points[xk]->AddEdge(tedges[2]); points[yk]->AddEdge(tedges[0]); points[yk]->AddEdge(tedges[1]); points[zk]->AddEdge(tedges[1]); points[zk]->AddEdge(tedges[2]); } sort(edges.begin(), edges.end(), _Internal::_edge_less); //classify each edge. Initially, they are either Inside or Boundary. //After edge-removal, we can have Hole edges when an Inside edge is removed. for(int i=0; i<edges.size(); ++i) { if(isBoundary(edges[i])) { edges[i]->type = _Internal::Boundary; } else { edges[i]->type = _Internal::Inside; } Node<_Internal::_edge*>* node = makeset(edges[i]); vnodes.push_back(node); edges[i]->node = node; } //make a cluster of boundary edges. Initially, there is only one cluster Node<_Internal::_edge*>* root = NULL; for(int i=0; i<edges.size(); ++i) { if(edges[i]->type == _Internal::Boundary) { if(root == NULL) { root = edges[i]->node; } else { merge(edges[i]->node, root); } } } }