Development of Fashion CAD System 12. Custom Classes Sungmin Kim SEOUL NATIONAL UNIVERSITY Topics Using Custom Classes Spline Curve 사용하기 TBSpline Class Introduction DXF (Drawing Exchange Format) 로저장하기 TDXFWriter Class Equation Solver 사용하기 TEquationSolver Class» 인체치수를이용한패턴디자인에의응용 2
Spline Curve TBSpline Class 의활용 Spline Curve Bezier 보다계산이복잡하나각각의조정점이전체형상에영향을적게미침 지정한점을지나도록 interpolate 할수있음 Poly Bezier Curve 로그리기도구현가능 3 Spline Curve TBSpline Class 의활용 Project 에필요한파일을추가 CustomClass.lib ptline Class 정의수정 #include class ptline public : ; #endif TBSpline void "TBSpline.h" *Spline; FormSpline(ptPoint**); ptline::ptline(int p1,int p2) Spline=0; ptline::ptline(int p1,int p2,int p3,int p4) Spline=0; ptline::ptline(ptline &L) Spline=0; ptline::~ptline() if (Spline) delete Spline; Spline=0; 4
Spline Curve TBSpline Class 의활용 FormSpline 함수의구성 Spline 에사용될점의갯수를지정 SetPointNum 함수 각점의좌표를입력 SetPoint 함수 Interpolate 함수로 Spline 을구성 Interpolate 함수 void ptline::formspline(ptpoint **P) Spline=new TBSpline; Spline->SetPointNum(4); for(i=0;i<4;i++) Spline->SetPoint(i,P[Point[i]]->x,P[Point[i]]->y); Spline->Interpolate(); 5 Spline Curve TBSpline Class 의활용 ptgarment Class 수정 AddLine 함수에 Spline 을구성하는코드를추가 void ptgarment::addline(int p1,int p2,int p3,int p4) Line=(ptLine**)realloc(Line,sizeof(ptLine*)*(LineNum+1)); Line[LineNum]=new ptline(p1,p2,p3,p4); Line[LineNum]->FormSpline(Point); LineNum++; DrawLine 함수를수정 CV->PolyBezier(pt,3); TBSpline *S=Line[l]->Spline; int pn=s->getdatapointnum(); TPoint *P=new TPoint[pn*3-2]; for(i=0;i<pn*3-2;i++) TPoint2D pt=s->getbeziercontrolpoint(i); ptpoint pt2=nc->screen(pt.x,pt.y); P[i].x=pt2.x; P[i].y=pt2.y; CV->PolyBezier(P,pn*3-3); delete[]p; 6
DXF Writer DXF 파일로저장하기 DXF (Drawing Exchange Format) AutoCAD의개발사인 AutoDesk에서만든규격 서로다른 CAD 시스템간데이터교환에널리이용됨 AAMA-DXF 라는표준규격도존재 (American Apparel Manufacturers Association) 7 DXF Writer YUKA CAD 와호환가능한구조 한패턴이하나의 Block 을구성 한패턴은하나의재단선으로구성됨 직선-Spline 모두를엮어서하나의 polyline 으로변환하기 Spline 을 Polyline 으로바꾸는것이문제» TBSpline 클래스활용 8
DXF Writer TMainForm 에메뉴추가 SaveDialog를복사 / 붙이기하여 SaveDXF dialog box 를생성 Filter, Title 등을수정 프로젝트에는 TDXFWriter.cpp 유닛을추가 9 DXF Writer Menu Handler 작성 void fastcall TMainForm::SaveasDXF1Click(TObject *Sender) TChildForm *C=(TChildForm*)ActiveMDIChild; if (C) SaveDXF->FileName=""; if (SaveDXF->Execute()) C->Garment->SaveAsDXF(SaveDXF->FileName); 10
DXF Writer 조건설정 패턴이없으면안됨 패턴은반드시한개의외곽선 (Line) 을가져야함 void ptgarment::saveasdxf(ansistring N) if (!PatternNum) Application->MessageBox("No pattern has been defined","caution",mb_iconexclamation MB_OK); return; for(i=0;i<patternnum;i++) if (!Pattern[i]->Line->Count) Application->MessageBox("Some patterns don't have a cut line","caution",mb_iconexclamation MB_OK); return; 11 DXF Writer Section 구조 Pattern section 하나의 block 이하나의패턴 geometry 를정의 Information section 각각의패턴을등록 void ptgarment::saveasdxf(ansistring N) TDXFWriter *D=new TDXFWriter; D->OpenFile(N); D->OpenPatternSection(); for(i=0;i<patternnum;i++) D->BeginPattern(Pattern[i]->Name); SaveAsPolyline(D,Pattern[i]); D->EndPattern(); D->EndPatternSection(); D->OpenInfoSection(); for(i=0;i<patternnum;i++) D->InsertPattern(Pattern[i]->Name); D->EndInfoSection(); D->CloseFile(); delete D; 12
DXF Writer SaveAsPolyline 함수의작성 void ptgarment::saveaspolyline(tdxfwriter *D,ptPattern *P) int i,j; int num=0; ptintegerlist *l=p->line; for(i=0;i<i->count;i++) ptline *L=Line[I->Number[i]]; if (!L->PointNum==2) // straight line num+=1; else L->Spline->GetUniformPointLength(10.0f); num+=l->spline->uniformpointnum; float *x=new float[num+100]; float *y=new float[num+100]; num=0; for(i=0;i<i->count;i++) ptline *L=Line[I->Number[i]]; if (L->PointNum==2) x[num]=point[l->point[0]]->x; y[num]=point[l->point[0]]->y; num++; else L->Spline->GetUniformPointLength(10.0f); int n=l->spline->uniformpointnum; for(j=0;j<n-1;j++) TPoint2D p=l->spline->uniformpoint[j].as2d(); x[num]=p.x; y[num]=p.y; num++; x[num]=x[0]; y[num]=y[0]; num++; D->WritePolyline(num,x,y); delete []x; delete []y; 13 DXF Writer 14
DXF Writer https://a360.autodesk.com/viewer 15 Equation Solver TEquationSolver 유닛을프로젝트에추가 변수이름, 값을입력 a=100 b=200 변수를포함한수식의값을계산 a+b*3 c+a/2 인체치수를이용한패턴제도에활용 인체치수를입력받아서변수에할당 점을정의할때단순한숫자가아니라변수를이용한수식으로정의 변수값을바꾸면패턴이변경되도록 16
Equation Solver TEquationSolver 핵심은 Reverse Polish Notation (RPN, 역폴란드법 ) 을이용한식의계산 5 + ((1 + 2) 4) 3 5 1 2 + 4 + 3 2 1 5 Stack FILO (First in Last Out) 17 Equation Solver 변수관리 UI 작성 TChildForm에메뉴추가 TVariableDialog.cpp Form 추가 TStringGrid DefaultColWidth=150 DefaultRowHeight=20 FixedCols=1 FixedRows=0 Name=LIST Options:goEditing=true RowCount=1 ScrollBars=ssVertical NAME VALUE 18
Equation Solver 변수관리 UI 작성 ptgarmentclass 에변수관리기능추가 #include "TEquationSolver.h" ptgarment::ptgarment() class ptgarment public : int int ObjectType; ViewPoint,ViewHull; TEquationSolver *Solver; Solver=new TEquationSolver; ptgarment::~ptgarment() delete Solver; Clear 할때도변수는지우지않음 Solver=0; Clear(); 19 Equation Solver Edit-Variables Event Handler 작성 TVariableDialog *V=VariableDialog; TEquationSolver *S=Garment->Solver; V->LIST->RowCount=S->VariableNum; V->LIST->Cells[0][0]=""; V->LIST->Cells[1][0]=""; for(i=0;i<s->variablenum;i++) V->LIST->Cells[0][i]=AnsiString(S->Variable[i].Name); V->LIST->Cells[1][i]=AnsiString(S->Variable[i].Value); V->ShowModal(); if (V->Result) S->ClearVariable(); for(i=0;i<v->list->rowcount;i++) if (V->LIST->Cells[0][i]!="") S->AddVariable(V->LIST->Cells[0][i],V->LIST->Cells[1][i].ToDouble()); Garment->Regenerate(); FormPaint(this); 20
Equation Solver Variable Dialog 의 Event Handler Add / Delete void fastcall TVariableDialog::Button1Click(TObject *Sender) if (NAME->Text!="" && VALUE->Text!="") for(i=0;i<list->rowcount;i++) if (LIST->Cells[0][i]==NAME->Text) return; if (LIST->Cells[0][0]!="") LIST->RowCount++; LIST->Cells[0][LIST->RowCount-1]=NAME->Text; LIST->Cells[1][LIST->RowCount-1]=VALUE->Text; void fastcall TVariableDialog::Button2Click(TObject *Sender) int r=list->row; if (r!=-1 && LIST->Cells[0][r]!="") for(i=r;i<list->rowcount-1;i++) LIST->Cells[0][i]=LIST->Cells[0][i+1]; LIST->Cells[1][i]=LIST->Cells[1][i+1]; if (LIST->RowCount==1) LIST->Cells[0][0]=""; LIST->Cells[1][0]=""; else LIST->RowCount--; 21 Equation Solver Variable Dialog 의 Event Handler Ok / Cancel void fastcall TVariableDialog::Button3Click(TObject *Sender) Result=1; Close(); void fastcall TVariableDialog::Button4Click(TObject *Sender) Result=0; Close(); 22
Equation Solver ptgarment Class 에서변수를저장하도록수정 void ptgarment::savetofilebinary(ansistring N) TNewFileStream *F=new TNewFileStream(N,fmCreate); F->WriteInt(1); // Version,20160624 F->WriteInt(StepNum); for(i=0;i<stepnum;i++) Step[i]->SaveToFileBinary(F); F->WriteInt(Solver->VariableNum); for(i=0;i<solver->variablenum;i++) F->WriteString(Solver->Variable[i].Name); F->WriteFloat(Solver->Variable[i].Value); delete F; void ptgarment::loadfromfilebinary(ansistring N) TNewFileStream *F=new TNewFileStream(N,fmOpenRead); int Version=F->ReadInt(); StepNum=F->ReadInt(); Step=(ptDesignStep**)calloc(StepNum,sizeof(ptDesignStep*)); for(i=0;i<stepnum;i++) Step[i]=new ptdesignstep; Step[i]->LoadFromFileBinary(F); int n=f->readint(); for(i=0;i<n;i++) AnsiString S=F->ReadString(); float f=f->readfloat(); Solver->AddVariable(S,f); delete F; Regenerate(); 23 Equation Solver 점의정의에변수를활용하기 좌표대신식을입력하게하기 입력창및코드수정 void fastcall TChildForm::AddXY1Click(TObject *Sender) Garment->AddPoint(PointXYDialog->X->Text,PointXYDialog->Y->Text); void fastcall TChildForm::MovePoint1Click(TObject *Sender) Garment->AddPointMove(PointXYDialog->X->Text,PointXYDialog->Y->Text); void fastcall TChildForm::AddDividePoint1Click(TObject *Sender) Garment->AddPointDivide(DividePointDialog->M->Text,DividePointDialog->N->Text); 24
Equation Solver ptdesignstep 의수정 x, y 값을float 값이아닌AnsiString으로받을수있도록변수를추가 ptdesignstep.h AnsiString void void AnsiString AnsiString XEqn,YEqn; SetXEquation(AnsiString S) XEqn=S; SetYEquation(AnsiString S) YEqn=S; GetXEquation() return XEqn; GetYEquation() return YEqn; ptdesignstep::ptdesignstep() XEqn=YEqn=""; void ptdesignstep::savetofilebinary(tnewfilestream *F) F->WriteString(XEqn); F->WriteString(YEqn); void ptdesignstep::loadfromfilebinary(tnewfilestream *F) XEqn=F->ReadString(); YEqn=F->ReadString(); 25 Equation Solver ptgarment 클래스의수정 void ptgarment::addpoint(ansistring X,AnsiString Y) ptdesignstep *S=AddStep(stAddPointXY); S->SetXEquation(X); S->SetYEquation(Y); float x,y; Solver->Evaluate(X,x); Solver->Evaluate(Y,y); AddPoint(x,y,StepNum-1); void ptgarment::addpointmove(ansistring X,AnsiString Y) for(i=0;i<selnum;i++) if (Sel[i]->Type==0) ptdesignstep *S=AddStep(stAddPointMove); S->AddIntParam(Sel[i]->Num); S->SetXEquation(X); S->SetYEquation(Y); float x,y; Solver->Evaluate(X,x); Solver->Evaluate(Y,y); AddPoint(Point[Sel[i]->Num]->x+x,Point[Sel[i]->Num]->y+y,StepNum-1); 26
Equation Solver ptgarment 클래스의수정 void ptgarment::addpointdivide(ansistring M,AnsiString N) ptdesignstep *S=AddStep(stAddPointDiv); S->AddIntParam(Sel[0]->Num); S->AddIntParam(Sel[1]->Num); S->SetXEquation(M); S->SetYEquation(N); float x,y,m,n; Solver->Evaluate(M,m); Solver->Evaluate(N,n); x=(m*point[sel[1]->num]->x+n*point[sel[0]->num]->x)/(m+n); y=(m*point[sel[1]->num]->y+n*point[sel[0]->num]->y)/(m+n); AddPoint(x,y,StepNum-1); 27 Equation Solver ptgarment 클래스의수정 Regenerate 함수의수정 switch(s->type) case staddpointxy: Solver->Evaluate(S->GetXEquation(),x); Solver->Evaluate(S->GetYEquation(),y); AddPoint(x,y,i); break; case staddpointmove: Solver->Evaluate(S->GetXEquation(),x); Solver->Evaluate(S->GetYEquation(),y); AddPoint(Point[S->GetIntParam(0)]->x+x,Point[S->GetIntParam(0)]->y+y,i); break; case staddpointdiv: Solver->Evaluate(S->GetXEquation(),m); Solver->Evaluate(S->GetYEquation(),n); x=(m*point[s->getintparam(1)]->x+n*point[s->getintparam(0)]->x)/(m+n); y=(m*point[s->getintparam(1)]->y+n*point[s->getintparam(0)]->y)/(m+n); AddPoint(x,y,i); break; 28
Equation Solver Point-Edit Property Event Handler 수정 void fastcall TChildForm::EditProperty2Click(TObject *Sender) float x,y; if (Garment->OnePoint()) ptdesignstep *S=Garment->PointStep(); switch(s->type) case staddpointxy: PointXYDialog->Caption="Set Coordinate"; PointXYDialog->X->Text=S->GetXEquation(); PointXYDialog->Y->Text=S->GetYEquation(); PointXYDialog->ShowModal(); if (PointXYDialog->Result==1) S->SetXEquation(PointXYDialog->X->Text); S->SetYEquation(PointXYDialog->Y->Text); break; case staddpointmove: PointXYDialog->Caption="Set Displacement"; PointXYDialog->X->Text=S->GetXEquation(); PointXYDialog->Y->Text=S->GetYEquation(); PointXYDialog->ShowModal(); if (PointXYDialog->Result==1) S->SetXEquation(PointXYDialog->X->Text); S->SetYEquation(PointXYDialog->Y->Text); break; case staddpointdiv: DividePointDialog->M->Text=S->GetXEquation(); DividePointDialog->N->Text=S->GetYEquation(); DividePointDialog->ShowModal(); if (DividePointDialog->Result) S->SetXEquation(DividePointDialog->M->Text); S->SetYEquation(DividePointDialog->N->Text); break; Garment->Regenerate(); FormPaint(this); 29