00001
00002
00003
00004
00005
00006
00007
00008 #define MODULE_TOOLS2 1
00009
00010 #include "design.h"
00011
00012
00013
00014
00015
00016 typedef struct tagVERTEXVERTEX{
00017 long vl,vr;
00018 } VERTEXVERTEX;
00019
00020 typedef struct tagFACEEXTRA{
00021 long extra,xxtra;
00022 } FACEEXTRA;
00023
00024 static int squeeze(int how);
00025 static double dspacing(long Va1, long Va2);
00026
00027
00028
00029
00030
00031 int Subdivide(long down_to_f, long down_to_e, long draw){
00032 face *fp;
00033 edge *ep;
00034 vertex *V0,*V1,*V2;
00035 long i,j,vl,vr,id,nf=0,ne=0,n,Nedge1,Nface1,Nv1;
00036 VERTEXVERTEX *vlist=NULL;
00037 FACEEXTRA *MainLp=NULL,*lp;
00038 HCURSOR hSave;
00039 if(NvertSelect > 32000){
00040 SendPrgmQuery(IDQ_WIRETOOBIG,0);
00041 return FAIL;
00042 }
00043
00044 if(down_to_f < Nface){
00045 if((MainLp=(FACEEXTRA *)X__Malloc(Nface*sizeof(FACEEXTRA))) == NULL){
00046 SendPrgmQuery(IDQ_NOMEM1,0);
00047 return FAIL;
00048 }
00049 fp=(MainFp+down_to_f); lp=(MainLp+down_to_f); nf=0;
00050 for(i=down_to_f;i<Nface;i++){
00051 lp->extra = -1;
00052 lp->xxtra = -1;
00053 V0=(MainVp+fp->V[0]); V1=(MainVp+fp->V[1]); V2=(MainVp+fp->V[2]);
00054 if((V0->status == SELECTED && V1->status == SELECTED) ||
00055 (V1->status == SELECTED && V2->status == SELECTED) ||
00056 (V2->status == SELECTED && V0->status == SELECTED))nf++;
00057 fp++; lp++;
00058 }
00059 }
00060 for(ep=(MainEp+down_to_e),ne=0,i=down_to_e;i<Nedge;i++){
00061 if((MainVp+ep->V[0])->status == SELECTED &&
00062 (MainVp+ep->V[1])->status == SELECTED)ne++;
00063 ep++;
00064 }
00065 if(ne == 0){
00066 if(MainLp != NULL)X__Free(MainLp);
00067 return FAIL;
00068 }
00069
00070 if((vlist=(VERTEXVERTEX *)X__Malloc(ne*sizeof(VERTEXVERTEX))) == NULL){
00071 if(MainLp != NULL)X__Free(MainLp);
00072 return FAIL;
00073 }
00074 if(!UpdateVertexHeap(Nvert+ne))goto EP1;
00075 if(!UpdateEdgeHeap(Nedge+ne+nf*3))goto EP1;
00076 if(!UpdateFaceHeap(Nface+nf*3))goto EP1;
00077 Nface1=Nface; Nedge1=Nedge;
00078 if(draw)hSave=SetCursor(ghcurWait);
00079 ep=(MainEp+down_to_e); n=0;
00080 for(i=down_to_e;i<Nedge1;i++){
00081 vl=ep->V[0]; V0=(MainVp+vl); vr=ep->V[1]; V1=(MainVp+vr);
00082 if(V0->status == SELECTED && V1->status == SELECTED){
00083 CreateVertex(); Nv1=Nvert-1;
00084 vlist[n].vl=vl; vlist[n].vr=vr; (MainVp+Nv1)->id=n; n++;
00085 (MainVp+Nv1)->xyz[0]=(V0->xyz[0] + V1->xyz[0])/2;
00086 (MainVp+Nv1)->xyz[1]=(V0->xyz[1] + V1->xyz[1])/2;
00087 (MainVp+Nv1)->xyz[2]=(V0->xyz[2] + V1->xyz[2])/2;
00088 CreateEdge(Nv1,ep->V[1]);
00089 ep->V[1]=Nv1;
00090 if(down_to_f < Nface1){
00091 fp=(MainFp+down_to_f); lp=(MainLp+down_to_f);
00092 for(j=down_to_f;j<Nface1;j++){
00093 id=0;
00094 if ((fp->V[0] == vl && fp->V[1] == vr) ||
00095 (fp->V[0] == vr && fp->V[1] == vl) )id=1;
00096 else if((fp->V[1] == vl && fp->V[2] == vr) ||
00097 (fp->V[1] == vr && fp->V[2] == vl) )id=2;
00098 else if((fp->V[2] == vl && fp->V[0] == vr) ||
00099 (fp->V[2] == vr && fp->V[0] == vl) )id=3;
00100 if(id != 0){
00101 if(lp->extra < 0)lp->extra=Nv1;
00102 else{
00103 if(lp->xxtra < 0)lp->xxtra=Nv1;
00104 else{
00105 CreateEdge(Nv1,lp->extra);
00106 CreateEdge(Nv1,lp->xxtra);
00107 CreateEdge(lp->extra,lp->xxtra);
00108 if (id == 1){
00109 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00110 fp->V[2],lp->xxtra,lp->extra))
00111 CreateFace(fp->V[2],lp->xxtra,lp->extra);
00112 else
00113 CreateFace(fp->V[2],lp->extra,lp->xxtra);
00114 CopyFaceProp(fp,(MainFp+Nface-1));
00115 if(vlist[(MainVp+lp->extra)->id].vl == fp->V[0] ||
00116 vlist[(MainVp+lp->extra)->id].vr == fp->V[0]){
00117 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00118 fp->V[0],Nv1,lp->extra))
00119 CreateFace(fp->V[0],Nv1,lp->extra);
00120 else
00121 CreateFace(fp->V[0],lp->extra,Nv1);
00122 CopyFaceProp(fp,(MainFp+Nface-1));
00123 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00124 fp->V[1],Nv1,lp->xxtra))
00125 CreateFace(fp->V[1],Nv1,lp->xxtra);
00126 else
00127 CreateFace(fp->V[1],lp->xxtra,Nv1);
00128 CopyFaceProp(fp,(MainFp+Nface-1));
00129 }
00130 else{
00131 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00132 fp->V[1],Nv1,lp->extra))
00133 CreateFace(fp->V[1],Nv1,lp->extra);
00134 else
00135 CreateFace(fp->V[1],lp->extra,Nv1);
00136 CopyFaceProp(fp,(MainFp+Nface-1));
00137 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00138 fp->V[0],Nv1,lp->xxtra))
00139 CreateFace(fp->V[0],Nv1,lp->xxtra);
00140 else
00141 CreateFace(fp->V[0],lp->xxtra,Nv1);
00142 CopyFaceProp(fp,(MainFp+Nface-1));
00143 }
00144 }
00145 else if(id == 2){
00146 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00147 fp->V[0],lp->xxtra,lp->extra))
00148 CreateFace(fp->V[0],lp->xxtra,lp->extra);
00149 else
00150 CreateFace(fp->V[0],lp->extra,lp->xxtra);
00151 CopyFaceProp(fp,(MainFp+Nface-1));
00152 if(vlist[(MainVp+lp->extra)->id].vl == fp->V[1] ||
00153 vlist[(MainVp+lp->extra)->id].vr == fp->V[1]){
00154 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00155 fp->V[1],Nv1,lp->extra))
00156 CreateFace(fp->V[1],Nv1,lp->extra);
00157 else
00158 CreateFace(fp->V[1],lp->extra,Nv1);
00159 CopyFaceProp(fp,(MainFp+Nface-1));
00160 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00161 fp->V[2],Nv1,lp->xxtra))
00162 CreateFace(fp->V[2],Nv1,lp->xxtra);
00163 else
00164 CreateFace(fp->V[2],lp->xxtra,Nv1);
00165 CopyFaceProp(fp,(MainFp+Nface-1));
00166 }
00167 else{
00168 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00169 fp->V[2],Nv1,lp->extra))
00170 CreateFace(fp->V[2],Nv1,lp->extra);
00171 else
00172 CreateFace(fp->V[2],lp->extra,Nv1);
00173 CopyFaceProp(fp,(MainFp+Nface-1));
00174 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00175 fp->V[1],Nv1,lp->xxtra))
00176 CreateFace(fp->V[1],Nv1,lp->xxtra);
00177 else
00178 CreateFace(fp->V[1],lp->xxtra,Nv1);
00179 CopyFaceProp(fp,(MainFp+Nface-1));
00180 }
00181 }
00182 else if(id == 3){
00183 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00184 fp->V[1],lp->xxtra,lp->extra))
00185 CreateFace(fp->V[1],lp->xxtra,lp->extra);
00186 else
00187 CreateFace(fp->V[1],lp->extra,lp->xxtra);
00188 CopyFaceProp(fp,(MainFp+Nface-1));
00189 if(vlist[(MainVp+lp->extra)->id].vl == fp->V[2] ||
00190 vlist[(MainVp+lp->extra)->id].vr == fp->V[2]){
00191 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00192 fp->V[2],Nv1,lp->extra))
00193 CreateFace(fp->V[2],Nv1,lp->extra);
00194 else
00195 CreateFace(fp->V[2],lp->extra,Nv1);
00196 CopyFaceProp(fp,(MainFp+Nface-1));
00197 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00198 fp->V[0],Nv1,lp->xxtra))
00199 CreateFace(fp->V[0],Nv1,lp->xxtra);
00200 else
00201 CreateFace(fp->V[0],lp->xxtra,Nv1);
00202 CopyFaceProp(fp,(MainFp+Nface-1));
00203 }
00204 else{
00205 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00206 fp->V[0],Nv1,lp->extra))
00207 CreateFace(fp->V[0],Nv1,lp->extra);
00208 else
00209 CreateFace(fp->V[0],lp->extra,Nv1);
00210 CopyFaceProp(fp,(MainFp+Nface-1));
00211 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00212 fp->V[2],Nv1,lp->xxtra))
00213 CreateFace(fp->V[2],Nv1,lp->xxtra);
00214 else
00215 CreateFace(fp->V[2],lp->xxtra,Nv1);
00216 CopyFaceProp(fp,(MainFp+Nface-1));
00217 }
00218 }
00219 if(IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00220 lp->xxtra,lp->extra,Nv1)){
00221 fp->V[0]=lp->xxtra;
00222 fp->V[1]=lp->extra;
00223 fp->V[2]=Nv1;
00224 }
00225 else{
00226 fp->V[0]=lp->xxtra;
00227 fp->V[1]=Nv1;
00228 fp->V[2]=lp->extra;
00229 }
00230 lp->extra = -1;
00231 lp->xxtra = -1;
00232 }
00233 }
00234 }
00235 fp++; lp++;
00236 }
00237 }
00238 }
00239 ep++;
00240 }
00241 if(down_to_f < Nface1){
00242 fp=(MainFp+down_to_f); lp=(MainLp+down_to_f);
00243 for(i=down_to_f;i<Nface1;i++){
00244 V0=(MainVp+fp->V[0]);
00245 V1=(MainVp+fp->V[1]);
00246 V2=(MainVp+fp->V[2]);
00247 if(lp->extra >= 0){
00248 if(V0->status == DESELECTED){
00249 if( IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00250 fp->V[0],lp->extra,fp->V[2]))
00251 CreateFace(fp->V[0],lp->extra,fp->V[2]);
00252 else
00253 CreateFace(fp->V[0],fp->V[2],lp->extra);
00254 CopyFaceProp(fp,(MainFp+Nface-1));
00255 CreateEdge(fp->V[0],lp->extra);
00256 fp->V[2] = lp->extra;
00257 }
00258 else if(V1->status == DESELECTED){
00259 if( IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00260 fp->V[1],lp->extra,fp->V[0]))
00261 CreateFace(fp->V[1],lp->extra,fp->V[0]);
00262 else
00263 CreateFace(fp->V[1],fp->V[0],lp->extra);
00264 CopyFaceProp(fp,(MainFp+Nface-1));
00265 CreateEdge(fp->V[1],lp->extra);
00266 fp->V[0] = lp->extra;
00267 }
00268 else if(V2->status == DESELECTED){
00269 if( IsFOSame(fp->V[0],fp->V[1],fp->V[2],
00270 fp->V[2],lp->extra,fp->V[1]))
00271 CreateFace(fp->V[2],lp->extra,fp->V[1]);
00272 else
00273 CreateFace(fp->V[2],fp->V[1],lp->extra);
00274 CopyFaceProp(fp,(MainFp+Nface-1));
00275 CreateEdge(fp->V[2],lp->extra);
00276 fp->V[1] = lp->extra;
00277 }
00278 }
00279 fp++; lp++;
00280 }
00281 }
00282 X__Free(vlist);
00283 if(MainLp != NULL)X__Free(MainLp);
00284 if(draw)SetCursor(hSave);
00285 return OK;
00286 EP1:
00287 if(MainLp != NULL)X__Free(MainLp);
00288 X__Free(vlist);
00289 return FAIL;
00290 }
00291
00292 int connected(long v1, long v2){
00293 edge *ep;
00294 long i;
00295 ep=MainEp; for(i=0;i<Nedge;i++){
00296 if( ((ep->V[0] == v1 && ep->V[1] == v2))
00297 ||((ep->V[0] == v2 && ep->V[1] == v1))
00298 )return 1;
00299 ep++;
00300 }
00301 return 0;
00302 }
00303
00304 int AutoFillFace(long down_to){
00305 long i,node,vp,NewVertex;
00306 long face_count,*face_list;
00307 if(down_to >= Nvert)return 0;
00308 if(NvertSelect > 32000){
00309 SendPrgmQuery(IDQ_WIRETOOBIG,0);
00310 return 0;
00311 }
00312 face_list = (long *)X__Malloc((NvertSelect+1)*10*sizeof(long));
00313 if(face_list == NULL)return 0;
00314 if(!UpdateVertexHeap(Nvert+1))return 0;
00315 if(!UpdateEdgeHeap(Nedge+(NvertSelect+1)*10))return 0;
00316 if(!UpdateFaceHeap(Nface+(NvertSelect+1)*10))return 0;
00317 NewVertex=Nvert;
00318 CreateVertex();
00319 (MainVp+NewVertex)->status=DESELECTED;
00320 (MainVp+NewVertex)->xyz[0]=NpointerX;
00321 (MainVp+NewVertex)->xyz[1]=NpointerY;
00322 (MainVp+NewVertex)->xyz[2]=NpointerZ;
00323 NvertSelect--; NvertDeselect++;
00324 for(i=0;i<Nvert;i++)(MainVp+i)->id=0;
00325 face_count=0;
00326 for(node=down_to;node<NewVertex;node++){;
00327 if((MainVp+node)->status == SELECTED){
00328 (MainVp+node)->id=1;
00329 CreateEdge(node,NewVertex);
00330 if(node < NewVertex-1)for(vp=node+1;vp < NewVertex; vp++){
00331 if((MainVp+vp)->status == SELECTED && (MainVp+vp)->id != 1){
00332 if(connected(node,vp)){
00333 CreateFace(node,vp,NewVertex);
00334 face_list[face_count]=(Nface-1);
00335 face_count++;
00336 }
00337 }
00338 }
00339 }
00340 }
00341 UpdateFaceHeap(Nface);
00342 UpdateEdgeHeap(Nedge);
00343 OrientateFaceNormals(-1,face_count,face_list);
00344 X__Free(face_list);
00345 return 1;
00346 }
00347
00348 static int squeeze(int how){
00349 long i,j,NewVertex;
00350 point p,TVp;
00351 vertex *V0,*V1;
00352 if(NvertSelect < 2)return 0;
00353 if(how == 1){p[0]=NpointerX; p[1]=NpointerY; p[2]=NpointerZ;}
00354 if(how == 2)get_centre(0,p,TVp,FALSE);
00355 for(i=0;i<Nvert;i++)(MainVp+i)->id=0;
00356 if(Nedge > 0)for(i=0;i<Nedge;i++){
00357 V0=(MainVp+(MainEp+i)->V[0]);
00358 V1=(MainVp+(MainEp+i)->V[1]);
00359 if(V0->status == SELECTED || V1->status == SELECTED){
00360 V0->id = -1;
00361 V1->id = -1;
00362 }
00363 }
00364 EraseVertex(1);
00365 NewVertex=0; if(Nvert > 0)for(i=0;i<Nvert;i++){
00366 if((MainVp+i)->id < 0)NewVertex++;
00367 }
00368 if(!UpdateVertexHeap(Nvert+1))return 0;
00369 if(!UpdateEdgeHeap(Nedge+NewVertex+1))return 0;
00370 if(!UpdateFaceHeap(Nface+NewVertex+1))return 0;
00371 NewVertex=Nvert;
00372 CreateVertex();
00373 (MainVp+NewVertex)->status=DESELECTED;
00374 (MainVp+NewVertex)->xyz[0]=p[0];
00375 (MainVp+NewVertex)->xyz[1]=p[1];
00376 (MainVp+NewVertex)->xyz[2]=p[2];
00377 NvertSelect--; NvertDeselect++;
00378 if(Nvert > 1)for(i=0;i<Nvert-1;i++){
00379 if((MainVp+i)->id < 0)CreateEdge(i,NewVertex);
00380 }
00381
00382 if(Nvert > 1)for(i=0;i<Nvert-1;i++){
00383 if((MainVp+i)->id < 0){
00384 for(j=0;j<Nvert-1;j++){
00385 if((MainVp+j)->id < 0 && connected(i,j))CreateFace(i,j,NewVertex);
00386 }
00387 (MainVp+i)->id=0;
00388 }
00389 }
00390 return 1;
00391 }
00392
00393 void Replace_Faces(int how, double threshold){
00394
00395 int id;
00396 long count;
00397 long i,vf;
00398 double th,d;
00399 vertex *vp,*vff;
00400 char temp[10];
00401 if(NvertSelect < 2){
00402 if(how == 0)SendPrgmQuery(IDQ_TOOFEWVERTICES,0);
00403 return;
00404 }
00405 if(NvertSelect > 32000){
00406 SendPrgmQuery(IDQ_WIRETOOBIG,0);
00407 return;
00408 }
00409 if(how == 0){
00410 d=(double)TVsizeX*(double)TVsizeY;
00411 for(i=0;i<Nvert;i++){
00412 vp=(MainVp+i);
00413 if(vp->status == SELECTED)d=min(d,DIS2(vp->xyz));
00414 }
00415 d=sqrt(fabs(d))/ruler; if(d < 0.001)d=0.0;
00416 if((id=DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_SQUEEZE),
00417 ghwnd_main,(DLGPROC)SqueezeDlgProc,(LPARAM)&d)) < 1)return;
00418 th=d;
00419 Save_Undo(2);
00420 }
00421 else {
00422 id=3;
00423 th=threshold*threshold;
00424 }
00425 if(id < 3)squeeze(id);
00426 else{
00427 if(th >= 0.0){
00428 if(how == 0){th=th*ruler; th *= th;}
00429 for(i=0;i<Nvert;i++){
00430 vp=(MainVp+i);
00431 if(vp->status == SELECTED)vp->status = INEDITOR;
00432 }
00433 while(1){
00434 vf = -1;
00435 for(i=0;i<Nvert;i++){
00436 vp=(MainVp+i);
00437 if(vp->status == INEDITOR){vf=i; break;}
00438 }
00439 if(vf < 0)break;
00440 vff=(MainVp+vf); vff->status = SELECTED; count=1;
00441 for(i=0;i<Nvert;i++){
00442 vp=(MainVp+i);
00443 if(vp->status == INEDITOR){
00444 d=(double)(vff->xyz[0]-vp->xyz[0])*(double)(vff->xyz[0]-vp->xyz[0])
00445 +(vff->xyz[1]-vp->xyz[1])*(double)(vff->xyz[1]-vp->xyz[1])
00446 +(vff->xyz[2]-vp->xyz[2])*(double)(vff->xyz[2]-vp->xyz[2]);
00447 if(d < th){count++; vp->status=SELECTED;}
00448 }
00449 }
00450 if(count == 1){
00451 vff->status=DESELECTED; NvertSelect--; NvertDeselect++;
00452 }
00453 else squeeze(2);
00454 }
00455 }
00456 }
00457 }
00458
00459 void ActionRotate(int axis, double angle, int draw){
00460 short shiftkey;
00461 double theta,ctheta,stheta
00462 ,dx,dy,dz;
00463 long i,tx,ty,tz;
00464 vertex *vp;
00465 struct np {int a; BOOL clock;} np;
00466 EDIT_ACTION=YES;
00467 theta = angle*PI/180.0;
00468 if(axis != 0 && WindowBox_view)theta *= -1.0;
00469 if(draw){
00470
00471
00472
00473 np.a=(int)angle;
00474 if(angle < 0)np.clock=TRUE;
00475 else np.clock=FALSE;
00476 if(!DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_ROTATE),ghwnd_main,
00477 (DLGPROC)RotateDlgProc,(LPARAM)&np))return;
00478 shiftkey=np.a;
00479 if(np.clock)angle = -1.0;
00480 else angle = 1.0;
00481 theta = (double)shiftkey*PI/180.0;
00482 if(angle < 0)theta *= -1.0;
00483 RotateNurbsAction(axis,theta);
00484 }
00485
00486
00487
00488
00489
00490 if(theta == 0.0)return;
00491 if(Nnurbs == 0 && NvertSelect == 0)return;
00492 if(NvertSelect == 0)goto UPDATE;
00493 ctheta=cos(theta);
00494 stheta=sin(theta);
00495
00496 vp=MainVp; for(i=0;i<Nvert;i++){
00497 if(vp->status == SELECTED){
00498 if (axis == 0){
00499 dx=(double)(vp->xyz[0]-NpointerX);
00500 dy=(double)(vp->xyz[1]-NpointerY);
00501 tx=NpointerX+(long)(ctheta*dx-stheta*dy);
00502 ty=NpointerY+(long)(stheta*dx+ctheta*dy);
00503 vp->xyz[0]=tx;
00504 vp->xyz[1]=ty;
00505 }
00506 else if(axis == 1){
00507 dx=(double)(vp->xyz[0]-NpointerX);
00508 dz=(double)(vp->xyz[2]-NpointerZ);
00509 tx=NpointerX+(long)(ctheta*dx-stheta*dz);
00510 tz=NpointerZ+(long)(stheta*dx+ctheta*dz);
00511 vp->xyz[0]=tx;
00512 vp->xyz[2]=tz;
00513 }
00514 else if(axis == 2){
00515 dy=(double)(vp->xyz[1]-NpointerY);
00516 dz=(double)(vp->xyz[2]-NpointerZ);
00517 ty=NpointerY+(long)(ctheta*dy-stheta*dz);
00518 tz=NpointerZ+(long)(stheta*dy+ctheta*dz);
00519 vp->xyz[1]=ty;
00520 vp->xyz[2]=tz;
00521 }
00522 }
00523 vp++;
00524 }
00525 UPDATE:
00526 RecalibrateAllBezier(); RecalibrateMapLocks();
00527 if(draw)DrawModel();
00528 }
00529
00530 void Explode(int type){
00531 struct TEMP {int id,id1; double dxx,dyy,dzz;} tc;
00532 double radius,distance,dmin,dmax;
00533 vertex *vp,*V0,*V1,*V2;
00534 int id,id1;
00535 face *fp;
00536 long i,g2;
00537 double medianX,medianY,medianZ,nmX,nmY,nmZ,dx,dy,dz,dxx,dyy,dzz;
00538 if(NvertSelect == 0){
00539 SendPrgmQuery(IDQ_OLD2,0);
00540 }
00541 else{
00542 if(type > 0){
00543 Save_Undo(1);
00544 }
00545 dmin=(double)MAXUNIT;
00546 dmax=0.0;
00547 if((vp=MainVp) != NULL)for(i=0;i<Nvert;i++){
00548 if(vp->status == SELECTED){
00549 distance=sqrt(
00550 (double)(vp->xyz[0]-NpointerX)*(double)(vp->xyz[0]-NpointerX)
00551 +(double)(vp->xyz[1]-NpointerY)*(double)(vp->xyz[1]-NpointerY)
00552 +(double)(vp->xyz[2]-NpointerZ)*(double)(vp->xyz[2]-NpointerZ)
00553 );
00554 if(distance < dmin)dmin=distance;
00555 if(distance > dmax)dmax=distance;
00556 }
00557 vp++;
00558 }
00559 if(dmin < MINUNIT)dmin=(double)MINUNIT;
00560 if(type > 0){
00561 dxx=1.5; dyy=1.5; dzz=1.5;
00562 tc.id=5; tc.id1=1;
00563 tc.dxx=dxx; tc.dyy=dyy; tc.dzz=dzz;
00564 DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_EXPLODE),
00565 ghwnd_main,(DLGPROC)ExplodeDlgProc,(LPARAM)&tc);
00566 id=tc.id; id1=tc.id1; dxx=tc.dxx; dyy=tc.dyy; dzz=tc.dzz;
00567 }
00568 else id=1;
00569 if(id <= 0)return;
00570 else if(id < 5){
00571 radius=(double)TVsizeX/2;
00572 if((vp=MainVp) != NULL)for(i=0;i<Nvert;i++){
00573 if(vp->status == SELECTED){
00574 if(id == 1){
00575 distance=sqrt(
00576 (double)(vp->xyz[0]-NpointerX)*(double)(vp->xyz[0]-NpointerX)
00577 +(double)(vp->xyz[1]-NpointerY)*(double)(vp->xyz[1]-NpointerY)
00578 +(double)(vp->xyz[2]-NpointerZ)*(double)(vp->xyz[2]-NpointerZ)
00579 );
00580 if(distance > 32){
00581 distance = radius/distance;
00582 vp->xyz[0]=NpointerX+(vp->xyz[0]-NpointerX)*distance;
00583 vp->xyz[1]=NpointerY+(vp->xyz[1]-NpointerY)*distance;
00584 vp->xyz[2]=NpointerZ+(vp->xyz[2]-NpointerZ)*distance;
00585 }
00586 }
00587 else if(id == 2){
00588 vp->xyz[2]=NpointerZ;
00589 }
00590 else if(id == 3){
00591 vp->xyz[0]=NpointerX;
00592 }
00593 else if(id == 4){
00594 vp->xyz[1]=NpointerY;
00595 }
00596 }
00597 vp++;
00598 }
00599 }
00600 else if(id == 5){
00601 if((fp=MainFp) != NULL)for(i=0;i<Nface;i++){
00602 V0=(MainVp+fp->V[0]); V1=(MainVp+fp->V[1]); V2=(MainVp+fp->V[2]);
00603 if(V0->status == SELECTED ||
00604 V1->status == SELECTED ||
00605 V2->status == SELECTED){
00606 medianX=(V0->xyz[0] + V1->xyz[0] + V2->xyz[0])/3.0;
00607 medianY=(V0->xyz[1] + V1->xyz[1] + V2->xyz[1])/3.0;
00608 medianZ=(V0->xyz[2] + V1->xyz[2] + V2->xyz[2])/3.0;
00609 if(id1 < 1){dx=dxx; dy=dyy; dz=dzz;}
00610 else if(id1 == 1){
00611 dx=1.0+dxx*(double)(rand())/32767.0;
00612 dy=1.0+dyy*(double)(rand())/32767.0;
00613 dz=1.0+dzz*(double)(rand())/32767.0;
00614 }
00615 else{
00616 distance=sqrt((medianX-NpointerX)*(medianX-NpointerX) +
00617 (medianY-NpointerY)*(medianY-NpointerY) +
00618 (medianZ-NpointerZ)*(medianZ-NpointerZ));
00619 if(distance > dmax){dx=1.0; dy=1.0; dz=1.0;}
00620 else{
00621 dx = dxx*0.666667/(1.0+distance/dmax);
00622 dy = dyy*0.666667/(1.0+distance/dmax);
00623 dz = dzz*0.666667/(1.0+distance/dmax);
00624 }
00625 }
00626 nmX = NpointerX+(medianX-NpointerX)*dx;
00627 nmY = NpointerY+(medianY-NpointerY)*dy;
00628 nmZ = NpointerZ+(medianZ-NpointerZ)*dz;
00629 V0->xyz[0] = V0->xyz[0] - medianX + nmX;
00630 V0->xyz[1] = V0->xyz[1] - medianY + nmY;
00631 V0->xyz[2] = V0->xyz[2] - medianZ + nmZ;
00632 V1->xyz[0] = V1->xyz[0] - medianX + nmX;
00633 V1->xyz[1] = V1->xyz[1] - medianY + nmY;
00634 V1->xyz[2] = V1->xyz[2] - medianZ + nmZ;
00635 V2->xyz[0] = V2->xyz[0] - medianX + nmX;
00636 V2->xyz[1] = V2->xyz[1] - medianY + nmY;
00637 V2->xyz[2] = V2->xyz[2] - medianZ + nmZ;
00638 }
00639 fp++;
00640 }
00641 }
00642 else if(id == 6){
00643 if((vp=MainVp) != NULL)for(i=0;i<Nvert;i++){
00644 if(vp->status == SELECTED){
00645 g2=grid_size/2;
00646 vp->xyz[0] = lrulerx+((vp->xyz[0]+
00647 (vp->xyz[0] >= 0 ? g2 : -g2)-lrulerx)/grid_size)*grid_size;
00648 vp->xyz[1] = lrulery+((vp->xyz[1]+
00649 (vp->xyz[1] >= 0 ? g2 : -g2)-lrulery)/grid_size)*grid_size;
00650 vp->xyz[2] = lrulerz+((vp->xyz[2]+
00651 (vp->xyz[2] >= 0 ? g2 : -g2)-lrulerz)/grid_size)*grid_size;
00652 }
00653 vp++;
00654 }
00655 }
00656 if(type > 0)DrawModel();
00657 }
00658 }
00659
00660 long get_closest_vertex(void){
00661 vertex *vp;
00662 long i,vf;
00663 double dmin,drange,d;
00664 dmin=(double)TVsizeX*(double)TVsizeX;
00665 drange=dmin/1024;
00666 vf = -1;
00667 if((vp=MainVp) != NULL)for(i=0;i<Nvert;i++){
00668 if(vp->status == SELECTED && intriview(vp)){
00669 d=(double)(vp->xyz[0]-NpointerX)*(double)(vp->xyz[0]-NpointerX)
00670 +(double)(vp->xyz[1]-NpointerY)*(double)(vp->xyz[1]-NpointerY)
00671 +(double)(vp->xyz[2]-NpointerZ)*(double)(vp->xyz[2]-NpointerZ);
00672 if(d < dmin && d < drange){
00673 dmin=d;
00674 vf=i;
00675 }
00676 }
00677 vp->id=0;
00678 vp++;
00679 }
00680 if(vf < 0){
00681 SendPrgmQuery(IDQ_NOPATHSTART,0);
00682 return -1;
00683 }
00684 return vf;
00685 }
00686
00687 void ExtrudeAlong(void){
00688 struct np {double expan,repeat_map;} data;
00689 long vp,vf,*va;
00690 double ndv1,mu,expan=1.0,l,ll,dmap,repeat_map=4.0;
00691 long Npath,i;
00692 vector v1,v2,v3,n,dv,vp1,vp2;
00693 int id,use_map_coord=0;
00694 vertex *Vp,*Va,*Va1;
00695 HCURSOR hSave;
00696 if(NvertSelect < 1)return;
00697 if(NvertSelect > 32000){
00698 SendPrgmQuery(IDQ_WIRETOOBIG,0);
00699 return;
00700 }
00701 if((vf=get_closest_vertex()) < 0)return;
00702 data.expan=expan;
00703 data.repeat_map=repeat_map;
00704 if((id=DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_EXTRUDEALONG),
00705 ghwnd_main,(DLGPROC)ExtrudeAlongDlgProc,(LPARAM)&data)) == FAIL)return;
00706 expan=data.expan;
00707 repeat_map=data.repeat_map;
00708
00709
00710 if((va=(long *)X__Malloc(NvertSelect*sizeof(long))) == NULL){
00711 SendPrgmQuery(IDQ_NOMEM2,0);
00712 return;
00713 }
00714 Npath=0; va[0]=vf; (MainVp+va[0])->id=1;
00715 (MainVp+vf)->status=DESELECTED; NvertSelect--; NvertDeselect++;
00716 vp=0; while(vp < Nvert){
00717 Vp=(MainVp+vp);
00718 if(Vp->status == SELECTED && Vp->id == 0 && connected(va[Npath],vp)){
00719 Npath++;
00720 va[Npath]=vp;
00721 Vp->id=1;
00722 Vp->status=DESELECTED;
00723 NvertSelect--; NvertDeselect++;
00724 vp=0;
00725 }
00726 else vp++;
00727 }
00728 Save_Undo(0);
00729 if(Npath > 0){
00730 if(id == 2){
00731 expan = exp(log(expan)/(double)Npath);
00732 }
00733 use_map_coord=0;
00734 {
00735 vp=0; while(vp < Nvert){
00736 Vp=(MainVp+vp);
00737 if(Vp->status == SELECTED && Vp->gp > 0){
00738 use_map_coord=1;
00739 break;
00740 }
00741 vp++;
00742 }
00743 }
00744 if(use_map_coord){
00745 l=0.0; ll=0.0;
00746 for(i=1;i<=Npath;i++){
00747 Va=(MainVp+va[i]); Va1=(MainVp+va[i-1]);
00748 l += sqrt(
00749 (double)(Va->xyz[0] - Va1->xyz[0])*
00750 (double)(Va->xyz[0] - Va1->xyz[0])+
00751 (double)(Va->xyz[1] - Va1->xyz[1])*
00752 (double)(Va->xyz[1] - Va1->xyz[1])+
00753 (double)(Va->xyz[2] - Va1->xyz[2])*
00754 (double)(Va->xyz[2] - Va1->xyz[2]));
00755 }
00756 }
00757 hSave=SetCursor(ghcurWait);
00758 for(i=1;i<=Npath;i++){
00759 Va=(MainVp+va[i]); Va1=(MainVp+va[i-1]);
00760 if(use_map_coord){
00761 ll += sqrt(
00762 (double)(Va->xyz[0] - Va1->xyz[0])*
00763 (double)(Va->xyz[0] - Va1->xyz[0])+
00764 (double)(Va->xyz[1] - Va1->xyz[1])*
00765 (double)(Va->xyz[1] - Va1->xyz[1])+
00766 (double)(Va->xyz[2] - Va1->xyz[2])*
00767 (double)(Va->xyz[2] - Va1->xyz[2]));
00768 dmap=ll/l*repeat_map;
00769 }
00770 POINT2VECTOR(Va->xyz ,v2);
00771 POINT2VECTOR(Va1->xyz,v1);
00772 VECSUB(v2,v1,v1)
00773 if(O_normalize(v1) == FAIL){
00774 SendPrgmQuery(IDQ_POINTSTOOCLOSE,0);
00775 goto EXIT;
00776 }
00777 if(i<Npath){
00778 POINT2VECTOR((MainVp+va[i+1])->xyz,v3);
00779 VECSUB(v3,v2,v2)
00780 if(O_normalize(v2) == FAIL){
00781 SendPrgmQuery(IDQ_POINTSTOOCLOSE,0);
00782 goto EXIT;
00783 }
00784 VECSUM(v1,v2,n)
00785 }
00786 else VECCOPY(v1,n)
00787 POINT2VECTOR((MainVp+va[i])->xyz,v2);
00788 ndv1=DOT(n,v1);
00789 if(fabs(ndv1) < 1.e-10){
00790 SendPrgmQuery(IDQ_NOLOOPBACK,0);
00791 goto EXIT;
00792 }
00793 if(!CreateAttachedCopy(1)){
00794 SendPrgmQuery(IDQ_NOMEM2,0);
00795 goto EXIT;
00796 }
00797 vp=0; while(vp < Nvert){
00798 Vp=(MainVp+vp);
00799 if(Vp->status == SELECTED){
00800 if(use_map_coord && Vp->gp > 0){
00801 Vp->y = dmap;
00802 }
00803 POINT2VECTOR(Vp->xyz,v3);
00804 VECSUB(v2,v3,v3)
00805 mu=DOT(n,v3)/ndv1;
00806 if(id < 2){
00807 Vp->xyz[0] += (long)(mu*v1[0]);
00808 Vp->xyz[1] += (long)(mu*v1[1]);
00809 Vp->xyz[2] += (long)(mu*v1[2]);
00810 }
00811 else{
00812 VECSCALE(mu,v1,dv)
00813 POINT2VECTOR(Vp->xyz,vp1);
00814 VECSUM(vp1,dv,vp2)
00815 POINT2VECTOR((MainVp+va[i])->xyz,vp1);
00816 VECSUB(vp2,vp1,dv)
00817 Vp->xyz[0] = (long)(vp1[0] + expan*dv[0]);
00818 Vp->xyz[1] = (long)(vp1[1] + expan*dv[1]);
00819 Vp->xyz[2] = (long)(vp1[2] + expan*dv[2]);
00820 }
00821 }
00822 vp++;
00823 }
00824 }
00825
00826 vp=0; while(vp < Nvert){
00827 Vp=(MainVp+vp);
00828 if(Vp->status == SELECTED){
00829 Vp->status=DESELECTED; NvertSelect--; NvertDeselect++;
00830 }
00831 vp++;
00832 }
00833 for(i=0;i<=Npath;i++)if((MainVp+va[i])->status == DESELECTED){
00834 (MainVp+va[i])->status=SELECTED;
00835 NvertSelect++; NvertDeselect--;
00836 }
00837 }
00838 EXIT:
00839 SetCursor(hSave);
00840 X__Free(va);
00841 DrawModel(); UpdateCounters();
00842 return;
00843 }
00844
00845 static double dspacing(long Va1, long Va2){
00846 vertex *va1,*va2;
00847 double d;
00848 va1=(MainVp+Va1); va2=(MainVp+Va2);
00849 d=(double)(va1->xyz[0] - va2->xyz[0]) *
00850 (double)(va1->xyz[0] - va2->xyz[0]) +
00851 (double)(va1->xyz[1] - va2->xyz[1]) *
00852 (double)(va1->xyz[1] - va2->xyz[1]) +
00853 (double)(va1->xyz[2] - va2->xyz[2]) *
00854 (double)(va1->xyz[2] - va2->xyz[2]);
00855 d=sqrt(d);
00856 return d;
00857 }
00858
00859 void JoinTwoCurves(void){
00860 HCURSOR hSave;
00861 vertex *Vp;
00862 long vp,vf1,vf2,*va1,*va2,*tempva,tempv,vactive,vnext,vcurrent;
00863 double d,dmin=1e32;
00864 long Npath1,Npath2,i,j,k0,k1,k2,flag;
00865 if(NvertSelect<6){
00866 SendPrgmQuery(IDQ_TOOFEWVERTICES,0);
00867 return;
00868 }
00869 if(NvertSelect > 32000){
00870 SendPrgmQuery(IDQ_WIRETOOBIG,0);
00871 return;
00872 }
00873 EDIT_ACTION=YES;
00874 hSave=SetCursor(ghcurWait);
00875 vp=0; vf1=vf2=-1;
00876 while(vp < Nvert){
00877 Vp=(MainVp+vp);
00878 if(Vp->status == SELECTED)vf1=vp;
00879 Vp->id=0;
00880 vp++;
00881 }
00882 if(vf1 < 0){
00883 SendPrgmQuery(IDQ_NOCURVE1,0);
00884 goto FINISH;
00885 }
00886
00887 if((va1=(long *)X__Malloc(NvertSelect*sizeof(long))) == NULL){
00888 SendPrgmQuery(IDQ_NOMEM2,0);
00889 goto FINISH;
00890 }
00891 Npath1=0; va1[0]=vf1; (MainVp+va1[0])->id=1;
00892 (MainVp+vf1)->status=DESELECTED; NvertSelect--; NvertDeselect++;
00893 vp=0; while(vp < Nvert){
00894 Vp=(MainVp+vp);
00895 if(Vp->status == SELECTED && Vp->id == 0 && connected(va1[Npath1],vp)){
00896 Npath1++;
00897 va1[Npath1]=vp;
00898 Vp->id=1;
00899 Vp->status=DESELECTED;
00900 NvertSelect--; NvertDeselect++;
00901 vp=0;
00902 }
00903 else vp++;
00904 }
00905
00906 vp=0;
00907 while(vp < Nvert){
00908 if((MainVp+vp)->status == SELECTED){
00909 vf2=vp; break;
00910 }
00911 vp++;
00912 }
00913 if(vf2 < 0){
00914 SendPrgmQuery(IDQ_NOCURVE2,0);
00915 X__Free(va1);
00916 goto GETOUT;
00917 }
00918
00919 if((va2=(long *)X__Malloc(NvertSelect*sizeof(long))) == NULL){
00920 SendPrgmQuery(IDQ_NOMEM2,0);
00921 X__Free(va1);
00922 goto GETOUT;
00923 }
00924 Npath2=0; va2[0]=vf2; (MainVp+va2[0])->id=2;
00925 (MainVp+vf2)->status=DESELECTED; NvertSelect--; NvertDeselect++;
00926 vp=0; while(vp < Nvert){
00927 Vp=(MainVp+vp);
00928 if(Vp->status == SELECTED && Vp->id == 0 && connected(va2[Npath2],vp)){
00929 Npath2++;
00930 va2[Npath2]=vp;
00931 Vp->id=2;
00932 Vp->status=DESELECTED;
00933 NvertSelect--; NvertDeselect++;
00934 vp=0;
00935 }
00936 else vp++;
00937 }
00938 Npath1++; Npath2++;
00939 if(Npath1 < 3 || Npath2 < 3 || NvertSelect > 0){
00940 SendPrgmQuery(IDQ_NOTSUITABLECURVE,0);
00941 X__Free(va1);
00942 X__Free(va2);
00943 goto GETOUT;
00944 }
00945 Save_Undo(0);
00946
00947 for(i=0;i<Npath1;i++)
00948 for(j=0;j<Npath2;j++){
00949 if((d=dspacing(va1[i],va2[j])) < dmin){
00950 dmin=d; vf1=va1[i]; vf2=va2[j];
00951 }
00952 }
00953
00954 Npath1=0; va1[0]=vf1; (MainVp+va1[0])->id=0;
00955 vp=0; while(vp < Nvert){
00956 Vp=(MainVp+vp);
00957 if(Vp->id == 1 && connected(va1[Npath1],vp)){
00958 Npath1++;
00959 va1[Npath1]=vp;
00960 Vp->id=0;
00961 vp=0;
00962 }
00963 else vp++;
00964 }
00965 Npath2=0; va2[0]=vf2; (MainVp+va2[0])->id=0;
00966 vp=0; while(vp < Nvert){
00967 Vp=(MainVp+vp);
00968 if(Vp->id == 2 && connected(va2[Npath2],vp)){
00969 Npath2++;
00970 va2[Npath2]=vp;
00971 Vp->id=0;
00972 vp=0;
00973 }
00974 else vp++;
00975 }
00976 if(Npath1 == 0 || Npath2 == 0){
00977 SendPrgmQuery(IDQ_NOJOIN,0);
00978 goto GETOUT;
00979 }
00980 Npath1++; Npath2++;
00981
00982
00983 if(Npath2 < Npath1){
00984
00985 tempv=vf1; vf1=vf2; vf2=tempv;
00986 tempva=va1; va1=va2; va2=tempva;
00987 i=Npath1; Npath1=Npath2; Npath2=i;
00988 }
00989
00990
00991
00992 if(dspacing(va1[1],va2[1]) > dspacing(va1[1],va2[Npath2-1])){
00993
00994
00995 for(i=1;i<=(Npath2-1)/2;i++){
00996 tempv=va2[i];
00997 va2[i]=va2[Npath2-i];
00998 va2[Npath2-i]=tempv;
00999 }
01000 }
01001
01002 if(!UpdateEdgeHeap(Nedge+2*(Npath1+Npath2+1)))goto UPDATE_HEAP;
01003 if(!UpdateFaceHeap(Nface+2*(Npath1+Npath2+4)))goto UPDATE_HEAP;
01004
01005 k0=1;
01006 CreateEdge(va1[0],va2[0]);
01007 (MainVp+va1[0])->id=0;
01008 for(i=1;i<Npath1;i++){
01009 dmin=1e32; k1= -1;
01010 if(k0 < Npath2)for(j=k0;j<Npath2;j++){
01011 if((d=dspacing(va1[i],va2[j])) < dmin){dmin=d; k1=j;}
01012 }
01013 if(k1 >= 0){
01014 k0=k1;
01015 (MainVp+va1[i])->id=k0;
01016 CreateEdge(va1[i],va2[k0]);
01017 }
01018 }
01019
01020 for(i=0;i<Npath1;i++){
01021 flag=0;
01022 vactive=va1[i];
01023 flag=0;
01024 k0=(long)((MainVp+va1[i])->id);
01025 vcurrent=va2[k0];
01026 if(i < Npath1-1){
01027 vnext=va1[i+1];
01028 k1=(long)((MainVp+va1[i+1])->id);
01029 k2=k1;
01030 }
01031 else{
01032 vnext=va1[0]; k1=Npath2; k2=0;
01033 }
01034 if(k1 > k0){
01035 if(k1 > k0+1){
01036 for(j=k0+1;j<k1;j++){
01037 vcurrent=va2[j];
01038 if(flag == 0){
01039 CreateEdge(vcurrent,vactive);
01040 CreateFace(vactive,vcurrent,va2[j-1]);
01041 if(dspacing(vcurrent,va2[k0]) > dspacing(vcurrent,va2[k2])){
01042
01043 CreateEdge(vcurrent,vnext);
01044 CreateFace(vactive,vcurrent,vnext);
01045 flag=1;
01046 }
01047 }
01048 else{
01049 CreateEdge(vcurrent,vnext);
01050 CreateFace(va2[j-1],vnext,vcurrent);
01051 }
01052 }
01053 }
01054
01055 if(flag == 0){
01056 CreateEdge(vcurrent,vnext);
01057 CreateFace(vactive,vnext,vcurrent);
01058 }
01059 CreateFace(vcurrent,vnext,va2[k2]);
01060 }
01061 else{
01062
01063 CreateFace(vactive,vcurrent,vnext);
01064 }
01065 }
01066 UPDATE_HEAP:
01067 UpdateFaceHeap(Nface);
01068 UpdateEdgeHeap(Nedge);
01069 X__Free(va1);
01070 X__Free(va2);
01071 GETOUT:
01072 DrawModel();
01073 UpdateCounters();
01074 FINISH:
01075 SetCursor(hSave);
01076 }
01077
01078 void Spin(int connect, int nsections, BOOL quiet, int Iaxis){
01079 HCURSOR hSave;
01080 int n=12,angle,i,axis,j,np1,np2;
01081 double theta=360.0,dmap=1.0;
01082 long *p1,*p2,vp,vps,vsave;
01083 vertex *Vp;
01084 if(NvertSelect < 1)return;
01085 if(NvertSelect > 32000){
01086 SendPrgmQuery(IDQ_WIRETOOBIG,0);
01087 return;
01088 }
01089 if(!quiet){
01090 if(Read1Int1Real("Lathe","# Sections","Angle",&n,3,100,&theta,
01091 -355.0,360.0,ghwnd_main) != OK)return;
01092 axis=ActiveView;
01093 }
01094 else{
01095 axis=Iaxis;
01096 n=nsections;
01097 theta=360.0;
01098 }
01099 angle=(int)theta;
01100
01101 dmap=4.0/(double)n*(double)angle/360.0;
01102 if(abs(angle) < 2)return;
01103 p1=NULL; p2=NULL;
01104 if(angle == 360){
01105 if(n < 3)return;
01106 theta =(double)angle/(double)n; n--;
01107 if(connect == 1){
01108 p1=(long *)X__Malloc(sizeof(long)*NvertSelect);
01109 if(p1 == NULL){
01110 SendPrgmQuery(IDQ_NOMEM2,0);
01111 return;
01112 }
01113 p2=(long *)X__Malloc(sizeof(long)*NvertSelect);
01114 if(p2 == NULL){
01115 SendPrgmQuery(IDQ_NOMEM2,0);
01116 X__Free(p1);
01117 return;
01118 }
01119 np1=0; vps=Nvert;
01120 vp=0; while(vp < Nvert){
01121 if((MainVp+vp)->status==SELECTED){*(p1+np1)=vp; np1++;}
01122 vp++;
01123 }
01124 }
01125 }
01126 else {
01127 n--;
01128 theta=(double)angle/(double)n;
01129 }
01130 if(!quiet){
01131 hSave=SetCursor(ghcurWait);
01132 Save_Undo(0);
01133 }
01134 for(i=0;i<n;i++){
01135 vsave=Nvert;
01136 if(connect==0 && !AddCopy(0))goto FINISHED;
01137 if(connect==1 && !CreateAttachedCopy(1)){
01138 if(p1 != NULL)X__Free(p1);
01139 if(p1 != NULL)X__Free(p2);
01140 goto FINISHED;
01141 }
01142 ActionRotate(axis,theta,0);
01143 {
01144 vp=vsave; while(vp < Nvert){
01145 Vp=(MainVp+vp);
01146 if(Vp->status == SELECTED && Vp->gp > 0)Vp->y += dmap;
01147 vp++;
01148 }
01149 }
01150 }
01151
01152 if(angle==360 && connect == 1){
01153
01154 if(!UpdateEdgeHeap(Nedge+2*np1))goto EXIT;
01155 if(!UpdateFaceHeap(Nface+2*np1))goto EXIT;
01156 np2=0;
01157 vp=vps; while(vp < Nvert){
01158 if((MainVp+vp)->status==SELECTED){
01159 *(p2+np2)=vp; np2++;
01160 }
01161 vp++;
01162 }
01163 if(np1 != np2){MessageBeep(MB_OK); goto EXIT;}
01164 for(i=0;i<np1;i++)CreateEdge(*(p1+i),*(p2+i));
01165 if(np1 > 1){
01166 for(i=0;i<np1-1;i++) for(j=i+1;j<np1;j++){
01167 if(connected(*(p1+i),*(p1+j))){
01168 CreateEdge(*(p1+i),*(p2+j));
01169 CreateFace(*(p1+i),*(p2+j),*(p2+i));
01170 CreateFace(*(p1+i),*(p1+j),*(p2+j));
01171 }
01172 }
01173 }
01174 EXIT:
01175 X__Free(p1);
01176 X__Free(p2);
01177 UpdateEdgeHeap(Nedge);
01178 UpdateFaceHeap(Nface);
01179 }
01180 FINISHED:
01181 if(!quiet){
01182 SetCursor(hSave);
01183 DrawModel(); UpdateCounters();
01184 }
01185 }
01186
01187 void CopyConnected(void){
01188 #define PATH 11
01189 int flag1=0,flag2=0;
01190 HCURSOR hSave;
01191 long vp,vp2,Nv;
01192 point centre,TVp;
01193 vector x;
01194 vertex *Vp;
01195 int i=0;
01196 if(NvertSelect < 1) return;
01197 if(NvertSelect > 32000){
01198 SendPrgmQuery(IDQ_WIRETOOBIG,0);
01199 return;
01200 }
01201 Save_Undo(0);
01202 SelectConnected(PATH);
01203 vp=0; vp2=-1;
01204 while(vp < Nvert){
01205 if((MainVp+vp)->status==PATH){
01206 flag1=1; vp2=vp;
01207 }
01208 else if((MainVp+vp)->status==SELECTED)flag2=1;
01209 vp++;
01210 }
01211 if(flag1 == 0){
01212 SendPrgmQuery(IDQ_NONEARVERTEX,0);
01213 return;
01214 }
01215 if(flag2 == 0){
01216 vp=0; while(vp < Nvert){
01217 if((MainVp+vp)->status==PATH)(MainVp+vp)->status=DESELECTED;
01218 vp++;
01219 }
01220 DrawModel(); UpdateCounters();
01221 SendPrgmQuery(IDQ_BADCURVE,0);
01222 return;
01223 }
01224 Nv=Nvert;
01225 hSave=SetCursor(ghcurWait);
01226 vp=0; while(vp < Nv){
01227 if((MainVp+vp)->status==PATH){
01228 if(i > 0){
01229 if(!AddCopy(0))goto FINISHED;
01230 }
01231 get_centre(1,centre,TVp,FALSE);
01232 Vp=(MainVp+vp);
01233 x[0]=Vp->xyz[0]-centre[0];
01234 x[1]=Vp->xyz[1]-centre[1];
01235 x[2]=Vp->xyz[2]-centre[2];
01236 vp2=0; while(vp2 < Nvert){
01237 Vp=(MainVp+vp2);
01238 if(Vp->status==SELECTED){
01239 Vp->xyz[0]+=x[0];
01240 Vp->xyz[1]+=x[1];
01241 Vp->xyz[2]+=x[2];
01242 }
01243 vp2++;
01244 }
01245 ++i;
01246 }
01247 vp++;
01248 }
01249 FINISHED:
01250 vp=0; while(vp < Nvert){
01251 if(Vp->status==SELECTED) {
01252 Vp->status=DESELECTED; NvertSelect--; NvertDeselect++;
01253 }
01254 vp++;
01255 }
01256 vp=0; while(vp < Nvert){
01257 Vp=(MainVp+vp);
01258 if(Vp->status==PATH) {
01259 Vp->status=SELECTED; ++NvertSelect; --NvertDeselect;
01260 }
01261 vp++;
01262 }
01263 SetCursor(hSave);
01264 DrawModel(); UpdateCounters();
01265 }
01266
01267 void Flip(void){
01268 HCURSOR hSave;
01269 struct np {int plane,weld;} data;
01270 vertex *Vp;
01271 long vp,vps;
01272 long NpX2,NpY2,NpZ2,toll,x,y,z;
01273 int sx,sy,swi,kid = -1;
01274 int id,plane,weld;
01275 data.plane=0;
01276 data.weld=0;
01277 if((id=DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_FLIP),
01278 ghwnd_main,(DLGPROC)FlipDlgProc,(LPARAM)&data)) == FAIL)return;
01279 plane=data.plane;
01280 weld=data.weld;
01281 if (ActiveView == TRITOP){
01282 if(plane == 0)kid=2; else kid=1;
01283 }
01284 else if(ActiveView == TRIFRONT){
01285 if(plane == 0)kid=3; else kid=1;
01286 }
01287 else if(ActiveView == TRIRIGHT){
01288 if(plane == 0)kid=3; else kid=2;
01289 }
01290 if(NvertSelect == 0 || kid < 0)return;
01291 if(weld){
01292
01293 GetWindowCoords(ActiveView,NpointerX,NpointerY,NpointerZ,&sx,&sy);
01294 if(plane == 0){if(sy < 4)sy += 3; else sy -= 3;}
01295 if(plane == 1){if(sx < 4)sx += 3; else sx -= 3;}
01296 GetWorldCoords(ActiveView,&x,&y,&z,sx,sy);
01297 if (kid == 1)toll=labs(NpointerX-x);
01298 else if(kid == 2)toll=labs(NpointerY-y);
01299 else if(kid == 3)toll=labs(NpointerZ-z);
01300
01301
01302 Save_Undo(2);
01303 hSave=SetCursor(ghcurWait);
01304 vps=Nvert;
01305 AddCopy(0);
01306 }
01307 else Save_Undo(1);
01308 NpX2=NpointerX*2;
01309 NpY2=NpointerY*2;
01310 NpZ2=NpointerZ*2;
01311 vp=0; while(vp < Nvert){
01312 Vp=(MainVp+vp);
01313 if(Vp->status == SELECTED){
01314 switch(kid){
01315 case 1: Vp->xyz[0] = NpX2-Vp->xyz[0]; break;
01316 case 2: Vp->xyz[1] = NpY2-Vp->xyz[1]; break;
01317 case 3: Vp->xyz[2] = NpZ2-Vp->xyz[2]; break;
01318 }
01319 }
01320 vp++;
01321 }
01322 if(weld){
01323 vp=0; while(vp < vps){
01324 Vp=(MainVp+vp);
01325 if(Vp->id >= 0 && Vp->status == DESELECTED){
01326 swi=0;
01327 switch(kid){
01328 case 1: if(labs(Vp->xyz[0] - NpointerX) < toll)swi=1; break;
01329 case 2: if(labs(Vp->xyz[1] - NpointerY) < toll)swi=1; break;
01330 case 3: if(labs(Vp->xyz[2] - NpointerZ) < toll)swi=1; break;
01331 }
01332 if(swi){Vp->status=SELECTED; NvertSelect++; NvertDeselect--;}
01333 }
01334 vp++;
01335 }
01336 vp=vps; while(vp < Nvert){
01337 Vp=(MainVp+vp);
01338 if(Vp->status == SELECTED){
01339 swi=0;
01340 switch(kid){
01341 case 1: if(labs(Vp->xyz[0] - NpointerX) > toll)swi=1; break;
01342 case 2: if(labs(Vp->xyz[1] - NpointerY) > toll)swi=1; break;
01343 case 3: if(labs(Vp->xyz[2] - NpointerZ) > toll)swi=1; break;
01344 }
01345 if(swi){Vp->status=DESELECTED; NvertSelect--; NvertDeselect++;}
01346 }
01347 vp++;
01348 }
01349 Replace_Faces(kid,(double)toll);
01350 SetCursor(hSave);
01351 }
01352 DrawModel(); UpdateCounters();
01353 }
01354
01355 #include "splines.c"
01356
01357 void SmoothCurve(void){
01358 vertex *Vp;
01359 long vp,vf,*va;
01360 double d,dmin,drange,dist,gds,gde,gs,ge,kx[4],ky[4],kz[4];
01361 long Npath,i;
01362 int id;
01363 char response[20];
01364 if(NvertSelect < 1)return;
01365 if(NvertSelect > 100){
01366 SendPrgmQuery(IDQ_WIRETOOBIG,0);
01367 return;
01368 }
01369 dmin=(double)TVsizeX*(double)TVsizeX;
01370 drange=dmin/1024;
01371 vp=0; vf= -1;
01372 while(vp < Nvert){
01373 Vp=(MainVp+vp);
01374 if(Vp->status == SELECTED && intriview(Vp)){
01375 d=(double)(Vp->xyz[0]-NpointerX)*(double)(Vp->xyz[0]-NpointerX)
01376 +(double)(Vp->xyz[1]-NpointerY)*(double)(Vp->xyz[1]-NpointerY)
01377 +(double)(Vp->xyz[2]-NpointerZ)*(double)(Vp->xyz[2]-NpointerZ);
01378 if(d < dmin && d < drange){
01379 dmin=d;
01380 vf=vp;
01381 }
01382 }
01383 Vp->id=0;
01384 vp++;
01385 }
01386 if(vf < 0){
01387 SendPrgmQuery(IDQ_NOPATHSTART,0);
01388 return;
01389 }
01390 if((va=(long *)X__Malloc(NvertSelect*sizeof(long))) == NULL){
01391 SendPrgmQuery(IDQ_NOMEM2,0);
01392 return;
01393 }
01394 Save_Undo(1);
01395 Npath=0; va[0]=vf; (MainVp+va[0])->id=1;
01396 vp=0; while(vp < Nvert){
01397 Vp=(MainVp+vp);
01398 if(Vp->status == SELECTED && Vp->id == 0 && connected(va[Npath],vp)){
01399 Npath++;
01400 va[Npath]=vp;
01401 Vp->id=1;
01402 vp=0;
01403 }
01404 else vp++;
01405 }
01406 Npath++;
01407 if(Npath > 4){
01408 dist=dspacing(va[Npath-2],va[1]);
01409 gds=dist/dspacing(va[1],va[0]); gde=dist/dspacing(va[Npath-1],va[Npath-2]);
01410 if(GetAsyncKeyState(VK_CONTROL) & 0x8000){
01411 sprintf(response,"1.0,1.0");
01412 RequestCharString(10,response,"Flexibility",ghwnd_main);
01413 if(sscanf(response,"%lf,%lf",&gs,&ge) == 2){
01414 if(gs < 0.01 || gs > 20)gs=1.0;
01415 if(ge < 0.01 || ge > 20)ge=1.0;
01416 gds *= gs; gde *= ge;
01417 }
01418 }
01419 else if(GetAsyncKeyState(VK_SHIFT) & 0x8000){
01420 gds *= 2; gde *= 2;
01421 }
01422 else if(GetAsyncKeyState(VK_MENU) & 0x8000){
01423 gds *= 4; gde *= 4;
01424 }
01425 gs = (double)((MainVp+va[1])->xyz[0] - (MainVp+va[0])->xyz[0])*gds;
01426 ge = (double)((MainVp+va[Npath-1])->xyz[0] - (MainVp+va[Npath-2])->xyz[0])*gde;
01427 SplinesG(kx,(double)(MainVp+va[1])->xyz[0],
01428 (double)(MainVp+va[Npath-2])->xyz[0],gs,ge);
01429 gs = (double)((MainVp+va[1])->xyz[1] - (MainVp+va[0])->xyz[1])*gds;
01430 ge = (double)((MainVp+va[Npath-1])->xyz[1] - (MainVp+va[Npath-2])->xyz[1])*gde;
01431 SplinesG(ky,(double)(MainVp+va[1])->xyz[1],
01432 (double)(MainVp+va[Npath-2])->xyz[1],gs,ge);
01433 gs = (double)((MainVp+va[1])->xyz[2] - (MainVp+va[0])->xyz[2])*gds;
01434 ge = (double)((MainVp+va[Npath-1])->xyz[2] - (MainVp+va[Npath-2])->xyz[2])*gde;
01435 SplinesG(kz,(double)(MainVp+va[1])->xyz[2],
01436 (double)(MainVp+va[Npath-2])->xyz[2],gs,ge);
01437 for(i=2;i<Npath-2;i++){
01438 gds=(double)(i-1)/(double)(Npath-3);
01439 (MainVp+va[i])->xyz[0] = (long)SplinesR(kx,gds);
01440 (MainVp+va[i])->xyz[1] = (long)SplinesR(ky,gds);
01441 (MainVp+va[i])->xyz[2] = (long)SplinesR(kz,gds);
01442 }
01443 }
01444 else{
01445 SendPrgmQuery(IDQ_TOOFEWVERTICES,0);
01446 }
01447 X__Free(va);
01448 DrawModel();
01449 }
01450