digital 3d anthropometry - laboratory of fashion technology -...
TRANSCRIPT
Sungmin Kim
SEOUL NATIONAL UNIVERSITY
Digital 3D Anthropometry
9. Data Analysis-2
Introduction Body Data Analysis 치수 측정
분석 범위 설정
폐곡선 찾기
Convex Hull 찾기
단면 측정
랜드마크간 측정
2
Data Analysis 분석범위 설정 단면에서 분석할 부분만 설정
TBodySection 에 데이터 추가
3
class TBodySection{...
float Range[2];bool DragStart;int TargetTPoint2D Start;TNewCanvas *NC;
...}
TBodySection::TBodySection(){...Range[0]=-200;Range[1]=200;DragStart=false;}
Range[0] Range[1]
Data Analysis 분석범위 설정 단면에서 분석할 부분만 설정
TCrossSectionDialog 의 마우스 핸들러 설정
4
void __fastcall TCrossSectionDialog::FormMouseDown(TObject *Sender,TMouseButton Button, TShiftState Shift, int X, int Y){Section->MouseDown(NC,Button,Shift,X,Y);}
void __fastcall TCrossSectionDialog::FormMouseMove(TObject *Sender, TShiftState Shift, int X, int Y){if (Section->MouseMove(Shift,X,Y)){
FormPaint(this);}
}
void __fastcall TCrossSectionDialog::FormMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y){Section->MouseUp(Button,Shift,X,Y);}
Data Analysis 분석범위 설정 단면에서 분석할 부분만 설정
TBodySection의 마우스 핸들러
5
void TBodySection::MouseDown(TNewCanvas *C,TMouseButton Button, TShiftState Shift, int X, int Y){NC=C;if (!DragStart){
TPoint2D P=NC->Real(X,Y);Target=FindTarget(P.x,P.y);if (Target!=-1){
DragStart=true;Start=P;}
}}
int TBodySection::FindTarget(float x,float y){float d1=fabs(Range[0]-x);float d2=fabs(Range[1]-x);if (d1<d2) return 0;return 1;}
Data Analysis 분석범위 설정 단면에서 분석할 부분만 설정
TBodySection의 마우스 핸들러
6
bool TBodySection::MouseMove(TShiftState Shift, int X, int Y){if (DragStart){
TPoint2D P=NC->Real(X,Y);float dx=P.x-Start.x;Range[Target]+=dx;Start=P;return true;}
return false;}
void TBodySection::MouseUp(TMouseButton Button, TShiftState Shift, int X, int Y){if (DragStart) DragStart=false;}
Data Analysis 분석범위 설정 단면에서 분석할 부분만 설정
TBodySection의 Draw 함수 수정
7
void TBodySection::Draw(TNewCanvas *C){int i;for(i=0;i<PointNum;i++){
if (Point[i].x<Range[0] || Point[i].x>Range[1]){C->DrawPixel(Point[i].x,Point[i].z,clRed);}
else{C->DrawPixel(Point[i].x,Point[i].z,clBlack);}
}C->SetPen(psSolid,1,clBlue);C->MoveTo(Range[0],500);C->LineTo(Range[0],-500);C->MoveTo(Range[1],500);C->LineTo(Range[1],-500);}
마우스로 이동
Data Analysis 분석범위 설정 화면 일부에 TNewCanvas 를 표시
화면 일부에 UI 구성
8
TOPTPanel
PBTPaintBox
Data Analysis 분석범위 설정 화면 일부에 TNewCanvas 를 표시
화면 일부에 UI 구성
– Canvas 를 PB->Canvas 로 변경– FormPaint 를 PBPaint 로 변경
9
void __fastcall TCrossSectionDialog::FormCreate(TObject *Sender){NC=new TNewCanvas(PB->Canvas,PB->Width,PB->Height);}
void __fastcall TCrossSectionDialog::FormResize(TObject *Sender){if (NC) delete NC;NC=new TNewCanvas(PB->Canvas,PB->Width,PB->Height);Section->FitToWindow(NC);FormPaint(this);}
void __fastcall TCrossSectionDialog::PBPaint(TObject *Sender){if (NC){
NC->Clear();Section->Draw(NC);}
}
Data Analysis 분석범위 설정 화면 일부에 TNewCanvas 를 표시
화면 일부에 UI 구성
– Mouse 핸들러를 PB 의 마우스 핸들러로 교체
10
void __fastcall TCrossSectionDialog::PBMouseDown(TObject *Sender,TMouseButton Button, TShiftState Shift, int X, int Y){Section->MouseDown(NC,Button,Shift,X,Y);}
void __fastcall TCrossSectionDialog::PBMouseMove(TObject *Sender,TShiftState Shift, int X, int Y){if (Section->MouseMove(Shift,X,Y)){
FormPaint(this);}
}
void __fastcall TCrossSectionDialog::PBMouseUp(TObject *Sender,TMouseButton Button, TShiftState Shift, int X, int Y){Section->MouseUp(Button,Shift,X,Y);}
Data Analysis 분석범위 설정 화면 일부에 TNewCanvas 를 표시
화면 일부에 UI 구성
11
Data Analysis 폐곡선 찾기 순차적으로 가까운 점을 찾아 연결하기
12
StartNext2nd Next
Data Analysis 폐곡선 찾기 버튼 추가 및 핸들러 구성
13
void __fastcall TCrossSectionDialog::Button2Click(TObject *Sender){Section->FindClosedPath();PBPaint(this);}
void __fastcall TCrossSectionDialog::SHOWPATHClick(TObject *Sender){PBPaint(this);}
void __fastcall TCrossSectionDialog::PBPaint(TObject *Sender){if (NC){
NC->Clear();Section->Draw(NC);if (SHOWPATH->Checked) Section->DrawPath(NC);}
}
Data Analysis 폐곡선 찾기 TBodySection 클래스 수정
14
class TBodySection{public:
int PathNum;TPoint2D *Path;int *valid;
void FindClosedPath();
};
TBodySection::TBodySection(){...PathNum=0;Path=0;}
TBodySection::~TBodySection(){...if (Path) delete[]Path;Path=0;PathNum=0;}
void TBodySection::DrawPath(TNewCanvas *C){int i;C->SetPen(psSolid,1,clRed);for(i=0;i<PathNum;i++){
if (!i) C->MoveTo(Path[i].x,Path[i].y);else C->LineTo(Path[i].x,Path[i].y);}
if (PathNum) C->LineTo(Path[0].x,Path[0].y);}
Data Analysis 폐곡선 찾기 FindClosedPath함수 구현
15
void TBodySection::FindClosedPath(){valid=new int[PointNum];
int i,start,next;for(i=0;i<PointNum;i++){
if (Point[i].x<Range[0] || Point[i].x>Range[1]) valid[i]=0;else{
valid[i]=1;start=i;}
}
if (Path) delete[]Path;Path=new TPoint2D[PointNum];PathNum=0;Path[PathNum++].Set(Point[start].x,Point[start].z);valid[start]=0;
do{next=FindNearestPoint(Point[start]);if (next!=-1){
Path[PathNum++].Set(Point[next].x,Point[next].z);valid[next]=0;start=next;}
} while(next!=-1);
delete[]valid;}
Data Analysis 폐곡선 찾기 FindNearestPoint 함수 구현
16
int TBodySection::FindNearestPoint(TPoint3D p){int i,MinP=-1;float d,MinD=100;for(i=0;i<PointNum;i++){
if (valid[i]){d=p.Distance(Point[i]);if (d<MinD){
MinD=d;MinP=i;}
}}
return MinP;}
Data Analysis Convex Hull 찾기 주어진 점을 포함하는 볼록 다각형
Graham Scan Method
17
Data Analysis Convex Hull 찾기 주어진 점을 포함하는 볼록 다각형
UI 구성
18
void __fastcall TCrossSectionDialog::Button3Click(TObject *Sender){Section->FindConvexHull();PBPaint(this);}
void __fastcall TCrossSectionDialog::SHOWHULLClick(TObject *Sender){PBPaint(this);}
SHOWHULLTCheckBox
Data Analysis Convex Hull 찾기 주어진 점을 포함하는 볼록 다각형
PBPaint 함수 수정
TBodySection 에 데이터 추가
19
void __fastcall TCrossSectionDialog::PBPaint(TObject *Sender){if (NC){
NC->Clear();Section->Draw(NC);if (SHOWPATH->Checked) Section->DrawPath(NC);if (SHOWHULL->Checked) Section->DrawHull(NC);}
}
class TBodySection{...
int HullNum;TPoint2D *Hull;void FindConvexHull();
};
TBodySection::TBodySection(){...
HullNum=0;Hull=0;}
TBodySection::~TBodySection(){...if (Hull) delete[]Hull;Hull=0;HullNum=0;}
Data Analysis Convex Hull 찾기 주어진 점을 포함하는 볼록 다각형
DrawHull 함수
DrawPath 함수와 똑같다 ?
– 반복되는 코드를 없애야 함– TNewCanvas 에 새로운 함수로 추가 가능
20
void TBodySection::DrawHull(TNewCanvas *C){int i;C->SetPen(psSolid,1,clBlue);for(i=0;i<HullNum;i++){
if (!i) C->MoveTo(Hull[i].x,Hull[i].y);else C->LineTo(Hull[i].x,Hull[i].y);}
if (PathNum) C->LineTo(Hull[0].x,Hull[0].y);}
Data Analysis Convex Hull 찾기 TNewCanvas에 새 함수 추가
TBodySection::Draw 함수 수정
21
void TNewCanvas::DrawPath(int n,TPoint2D *P){int i;for(i=0;i<n;i++){
if (!i) MoveTo(P[i].x,P[i].y);else LineTo(P[i].x,P[i].y);}
if (n) LineTo(P[0].x,P[0].y);}
void TBodySection::DrawPath(TNewCanvas *C){C->SetPen(psSolid,1,clRed);C->DrawPath(PathNum,Path);}
void TBodySection::DrawHull(TNewCanvas *C){C->SetPen(psSolid,1,clBlue);C->DrawPath(HullNum,Hull);}
Data Analysis Convex Hull 찾기
TConvexHull.cpp 외부 코드 활용
Project 에 추가
TBodySection.h 에서 #include "TConvexHull.h" 로 헤더를 포함
22
void TBodySection::FindConvexHull(){if (Hull) delete[]Hull;int i,PNum=0;;TPoint2D *P=new TPoint2D[PointNum];for(i=0;i<PointNum;i++){
if (Point[i].x>=Range[0] && Point[i].x<=Range[1]){P[PNum++].Set(Point[i].x,Point[i].z);}
}TConvexHull *CH=new TConvexHull(PNum,P);HullNum=CH->HullNum;Hull=new TPoint2D[HullNum];for(i=0;i<HullNum;i++){
Hull[i]=CH->Hull[i];}
delete CH;delete []P;}
Data Analysis Convex Hull 찾기
23
Closed Path Convex Hull
Data Analysis 단면 측정 측정 결과 표시를 위한 UI 수정
24
RESULTTListBox
void __fastcall TCrossSectionDialog::Button4Click(TObject *Sender){Section->Measure(RESULT);}
Data Analysis 단면 측정 Measure 함수
25
void TBodySection::Measure(TListBox *L){int i;float mx,my,Mx,My;mx=my=10000;Mx=My=-10000;for(i=0;i<PointNum;i++){
if (Point[i].x>=Range[0] && Point[i].x<=Range[1]){if (Point[i].x<mx) mx=Point[i].x;if (Point[i].z<my) my=Point[i].z;if (Point[i].x>Mx) Mx=Point[i].x;if (Point[i].z>My) My=Point[i].z;}
}char Buf[100];L->Items->Clear();sprintf(Buf,"Width = %.1f",Mx-mx);L->Items->Add(AnsiString(Buf));sprintf(Buf,"Depth = %.1f",My-my);L->Items->Add(AnsiString(Buf));sprintf(Buf,"Surface Girth =%.1f",GetGirth(PathNum,Path));L->Items->Add(AnsiString(Buf));sprintf(Buf,"Convex Girth =%.1f",GetGirth(HullNum,Hull));L->Items->Add(AnsiString(Buf));}
float TBodySection::GetGirth(int n,TPoint2D *p){float l=0;int i,j;for(i=0;i<n;i++){
j=(i==n-1) ? 0 : i+1;l+=p[i].Distance(p[j]);}
return l;}
Data Analysis Landmark 간 측정 Landmark 선택을 위한 UI 수정 및 핸들러 구성
26
void __fastcall TMainForm::Button12Click(TObject *Sender){if (!Body) return;int num=0;int mark[2];int i=0;while(i<L_LIST->Items->Count && num<2){
if (L_LIST->Selected[i]){mark[num++]=i;}
i++;}
if (num!=2) return;TPoint3D p1,p2;p1=Body->Landmark[mark[0]]->Position;p2=Body->Landmark[mark[1]]->Position;
char Buf[300];sprintf(Buf,"dx=%.1f\ndy=%.1f\ndz=%.1f\ndistance=%.1f",fabs(p1.x-p2.x),fabs(p1.y-p2.y),fabs(p1.z-p2.z),p1.Distance(p2));
ShowMessage(AnsiString(Buf));}MultiSelect=true