프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

hytos / ID2.Manager / ID2.Manager / Controls / Classify.cs @ 32acdfb1

이력 | 보기 | 이력해설 | 다운로드 (48.4 KB)

1
using devDept.Eyeshot;
2
using devDept.Eyeshot.Entities;
3
using devDept.Eyeshot.Translators;
4
using devDept.Geometry.Entities;
5
using GemBox.Spreadsheet;
6
using ID2.Manager.Common;
7
using ID2.Manager.Data.Models;
8
using System;
9
using System.Collections.Generic;
10
using System.ComponentModel;
11
using System.Data;
12
using System.Drawing;
13
using System.IO;
14
using System.Linq;
15
using System.Runtime.InteropServices;
16
using System.Text;
17
using System.Threading.Tasks;
18
using System.Windows.Forms;
19
using Telerik.WinControls;
20
using Telerik.WinControls.UI;
21
using Telerik.Windows.Documents.Fixed.FormatProviders.Pdf;
22
using Telerik.Windows.Documents.Fixed.Model;
23
using Telerik.Windows.Documents.Fixed.Model.Editing;
24

    
25
namespace ID2.Manager.Controls
26
{
27
    public partial class Classify : UserControl
28
    {
29
        class DocAttrValue
30
        {
31
            public DocAttrValue(string DocNo, Dictionary<string, List<KeyValuePair<string, string>>> _BlockAttrValueList)
32
            {
33
                this.DocNo = DocNo;
34
                this.BlockAttrValueList = _BlockAttrValueList;
35
            }
36

    
37
            public string DocNo { get; set; }
38
            public Dictionary<string, List<KeyValuePair<string, string>>> BlockAttrValueList { get; set; }
39
        }
40

    
41
        public delegate void DocumentSelected(Documents doc);
42

    
43
        readonly Informations informations = Informations.Instance;
44
        readonly string IniFilePath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), 
45
            Application.ProductName, $"{Application.ProductName}.ini");
46

    
47
        #region 기본값
48
        private static double Tolerance = 0;
49
        private static double Simularity { get; set; } = 80;
50
        private static double LengthToleranceRatio { get; set; } = 0.1;
51

    
52
        private static Font UnmatchedFont = new System.Drawing.Font("Segoe UI", 9F, FontStyle.Italic);
53
        private static Font MatchedFont = new System.Drawing.Font("Segoe UI", 9F, FontStyle.Bold);
54

    
55
        private string dwgExtension { get; } = ".dwg";
56
        #endregion
57

    
58
        class DrawingGroup
59
        {
60
            public string GroupNo { get; } = Guid.NewGuid().ToString();
61
            public List<string> Drawings {get;} = new List<string>();
62
        }
63

    
64
        private RadProgressBarElement _progressBar = null;
65

    
66
        public Classify(RadProgressBarElement progressBar)
67
        {
68
            InitializeComponent();
69
            this.radGridViewDocument.AutoSizeColumnsMode = Telerik.WinControls.UI.GridViewAutoSizeColumnsMode.Fill;
70

    
71
            this.Load += Verification_Load;
72
            this.radSpinEditorTolerance.ValueChanged += RadSpinEditorTolerance_ValueChanged;
73
            this.radButtonExceptLayer.Click += RadButtonExceptLayer_Click;
74
            this.radSpinEditorSimularity.ValueChanged += RadSpinEditorSimularity_ValueChanged;
75

    
76
            this.radButtonClassify.Click += RadButtonClassify_Click;
77
            this.radButtonExtractText.Click += RadButtonExtractText_Click;
78

    
79
            this.designDrawing.ActionMode = actionType.SelectVisibleByPickDynamic;
80
            this.designDrawing.Selection.ColorDynamic = Color.FromArgb(80, Color.OrangeRed);
81
            this.designDrawing.Selection.HaloInnerColor = Color.FromArgb(255, Color.OrangeRed);
82
            this.designDrawing.Selection.HaloOuterColor = Color.FromArgb(64, Color.OrangeRed);
83
            this.designDrawing.Selection.HaloWidthPolygons = 4;
84
            this.designDrawing.Selection.HaloWidthWires = 2;
85

    
86
            _progressBar = progressBar;
87
        }
88

    
89
        /// <summary>
90
        /// 선택한 도면에서 텍스트를 읽어 엑셀로 추출한다.
91
        /// </summary>
92
        /// <param name="sender"></param>
93
        /// <param name="e"></param>
94
        private void RadButtonExtractText_Click(object sender, EventArgs e)
95
        {
96
            void OpenDrawing(string FilePath)
97
            {
98
                if (!File.Exists(FilePath)) return;
99
                #region 다른 프로세스에서 파일을 열고 있는 경우 처리
100
                using (var fs = File.Open(FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
101
                #endregion
102

    
103
                {
104
                    devDept.Eyeshot.Translators.ReadAutodesk ra = new devDept.Eyeshot.Translators.ReadAutodesk(fs);
105
                    ra.DoWork();
106
                    ra.AddToScene(designDrawing);
107
                }
108
            }
109

    
110
            var docs = this.radGridViewDocument.Rows.Where(x => Convert.ToBoolean(x.Cells["Checked"].Value))
111
                .Select(x => x.DataBoundItem as ID2.Manager.Data.Models.Documents).ToList();
112
            var DocBlockAttrValueList = new List<DocAttrValue>();
113

    
114
            _progressBar.Maximum = docs.Count;
115
            _progressBar.Value1 = 0;
116
            for (int i = 0; i < docs.Count; ++i)
117
            {
118
                this.designDrawing.Entities.Clear();
119
                this.designDrawing.Blocks.Clear();
120

    
121
                string DwgFolder = System.IO.Path.Combine(informations.FindID2LocalPath(docs.ElementAt(i).RefProjectCode), "drawings", "Native");
122
                string DocNo = docs.ElementAt(i).DocumentNo;
123
                string FilePath = System.IO.Path.Combine(DwgFolder, $"{DocNo}{dwgExtension}");
124
                OpenDrawing(FilePath);
125

    
126
                #region 블럭의 속성을 읽음
127
                var TitleBlocks = this.designDrawing.Entities.Where(x => x is devDept.Eyeshot.Entities.BlockReference blkref 
128
                && Forms.ExceptLayer.TitleBlockAttribute.Exists(y => y.BlockName.Equals(blkref.BlockName)))
129
                    .Select(x => x as devDept.Eyeshot.Entities.BlockReference).ToList();
130

    
131
                var BlockAttrValueList = new Dictionary<string, List<KeyValuePair<string, string>>>();
132
                foreach(var blkref in TitleBlocks)
133
                {
134
                    var AttrValueList = new List<KeyValuePair<string, string>>();
135
                    var AttrNameList = Forms.ExceptLayer.TitleBlockAttribute.Where(x => x.BlockName.Equals(blkref.BlockName))
136
                        .Select(x => x.AttrName).ToList();
137
                    foreach (var attr in blkref.Attributes.Where(x => AttrNameList.Contains(x.Key)))
138
                    {
139
                        var AttrNameValue = new KeyValuePair<string, string>(attr.Key, attr.Value.Value);
140
                        AttrValueList.Add(AttrNameValue);
141
                    }
142
                    BlockAttrValueList.Add(Guid.NewGuid().ToString(), AttrValueList);
143
                }
144

    
145
                var DocBlockAttrValue = new DocAttrValue(DocNo, BlockAttrValueList);
146
                DocBlockAttrValueList.Add(DocBlockAttrValue);
147
                #endregion
148

    
149
                _progressBar.Value1 += 1;
150
                Application.DoEvents();
151
            }
152

    
153
            #region 엑셀 파일로 저장
154
            using (SaveFileDialog sfd = new SaveFileDialog()
155
            {
156
                Filter = "Excel files (*.xlsx)|*.xlsx",
157
                Title = "Save an excel file",
158
                RestoreDirectory = true,
159
                CheckPathExists = true,
160
                OverwritePrompt = true
161
            })
162
            {
163
                if (sfd.ShowDialog() == DialogResult.OK)
164
                {
165
                    var workbook = new ExcelFile();
166
                    // Add new sheet.
167
                    var worksheet = workbook.Worksheets.Add("TEXT");
168
                    worksheet.Cells[0, 0].Value = "FILE NAME";
169

    
170
                    #region 속성 이름 작성
171
                    var AttrNameList = Forms.ExceptLayer.TitleBlockAttribute.Select(x => x.AttrName).Distinct().ToList();
172
                    for (int i = 0; i < AttrNameList.Count; ++i)
173
                    {
174
                        worksheet.Cells[0, i + 1].Value = AttrNameList[i];
175
                    }
176
                    #endregion
177

    
178
                    int row = 1;
179
                    foreach(var doc in DocBlockAttrValueList)
180
                    {
181
                        foreach(var key in doc.BlockAttrValueList.Keys)
182
                        {
183
                            worksheet.Cells[row, 0].Value = doc.DocNo;
184
                            for (int col = 0; col < doc.BlockAttrValueList[key].Count; col++)
185
                            {
186
                                worksheet.Cells[row, col + 1].Value = doc.BlockAttrValueList[key][col].Value;
187
                            }
188
                            row++;
189
                        }
190
                    }
191

    
192
                    workbook.Save(sfd.FileName);
193
                }
194
            }
195
            #endregion
196

    
197
            this.designDrawing.Entities.Clear();
198
            this.designDrawing.Blocks.Clear();
199
            RadMessageBox.Show("Extracting text is complete.");
200
        }
201

    
202
        private void RadSpinEditorSimularity_ValueChanged(object sender, EventArgs e)
203
        {
204
            double simularity = Convert.ToDouble(this.radSpinEditorSimularity.Value);
205
            Classes.ID2Helper.IniWriteValue(IniFilePath, "Verification", "Simularity", simularity.ToString());
206
            Classify.Simularity = simularity;
207
        }
208

    
209
        private void RadButtonClassify_Click(object sender, EventArgs e)
210
        {
211
            void OpenDrawing(string FilePath, string LayerName, Color color)
212
            {
213
                if (!File.Exists(FilePath)) return;
214
                #region 다른 프로세스에서 파일을 열고 있는 경우 처리
215
                using (var fs = File.Open(FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
216
                #endregion
217

    
218
                {
219
                    devDept.Eyeshot.Translators.ReadAutodesk ra = new devDept.Eyeshot.Translators.ReadAutodesk(fs);
220
                    ra.DoWork();
221
                    var min = ra.Min;
222
                    if (!ra.Layers.Contains(LayerName)) ra.Layers.Add(LayerName, color);
223
                    foreach (var ent in ra.Entities)
224
                    {
225
                        /// 도면을 원점으로 맞춘다.
226
                        if (min.X != 0 && min.Y != 0) ent.Translate(-min.X, -min.Y);
227
                        ent.LayerName = LayerName;
228
                    }
229
                    ra.AddToScene(designDrawing);
230
                }
231
            }
232

    
233
            var DrawingGroupColl = new List<DrawingGroup>();
234

    
235
            var docs = this.radGridViewDocument.Rows.Where(x => Convert.ToBoolean(x.Cells["Checked"].Value))
236
                .Select(x => x.DataBoundItem as ID2.Manager.Data.Models.Documents).ToList();
237
            docs.ForEach(x => x.Simularity = string.Empty);
238

    
239
            #region 전체 비교 횟수 파악
240
            int sum = 0;
241
            for (int i = 0; i < docs.Count - 1; ++i)
242
            {
243
                for (int j = i + 1; j < docs.Count; ++j) sum++;
244
            }
245
            #endregion
246
            _progressBar.Maximum = sum;
247
            _progressBar.Value1 = 0;
248
            for (int i = 0;i < docs.Count - 1;++i)
249
            {
250
                string FirstDwgFolder = System.IO.Path.Combine(informations.FindID2LocalPath(docs.ElementAt(i).RefProjectCode), "drawings", "Native");
251
                string FirstDocNo = docs.ElementAt(i).DocumentNo;
252
                string FirstFilePath = System.IO.Path.Combine(FirstDwgFolder, $"{FirstDocNo}{dwgExtension}");
253
                for (int j = i + 1;j < docs.Count;++j)
254
                {
255
                    this.designDrawing.Entities.Clear();
256
                    this.designDrawing.Blocks.Clear();
257

    
258
                    OpenDrawing(FirstFilePath, "First", Color.FromArgb(44, 44, 44));
259

    
260
                    string SecondDwgFolder = System.IO.Path.Combine(informations.FindID2LocalPath(docs.ElementAt(j).RefProjectCode), "drawings", "Native");
261
                    string SecondDocNo = docs.ElementAt(j).DocumentNo;
262
                    string SecondFilePath = System.IO.Path.Combine(SecondDwgFolder, $"{SecondDocNo}{dwgExtension}");
263
                    OpenDrawing(SecondFilePath, "Second", Color.FromArgb(155, 155, 155));
264

    
265
                    var FirstEntities = this.designDrawing.Entities.Where(x => x.LayerName == "First").ToList();
266
                    var SecondEntities = this.designDrawing.Entities.Where(x => x.LayerName == "Second").ToList();
267
                    if (FirstEntities.Any() && SecondEntities.Any())
268
                    {
269
                        double simularity = 100 - CompareDrawing(designDrawing, FirstEntities, SecondEntities);
270
                        if (simularity >= Classify.Simularity)
271
                        {
272
                            var group = DrawingGroupColl.FirstOrDefault(x => x.Drawings.Exists(y => y.Equals(FirstDocNo) || y.Equals(SecondDocNo)));
273
                            if (group != null)
274
                            {
275
                                if (!group.Drawings.Exists(x => x.Equals(FirstDocNo))) group.Drawings.Add(FirstDocNo);
276
                                if (!group.Drawings.Exists(x => x.Equals(SecondDocNo))) group.Drawings.Add(SecondDocNo);
277
                            }
278
                            else
279
                            {
280
                                group = new DrawingGroup();
281
                                group.Drawings.Add(FirstDocNo);
282
                                group.Drawings.Add(SecondDocNo);
283
                                DrawingGroupColl.Add(group);
284
                            }
285
                        }
286
                    }
287

    
288
                    _progressBar.Value1 += 1;
289
                    Application.DoEvents();
290
                }
291
            }
292

    
293
            foreach(var group in DrawingGroupColl)
294
            {
295
                group.Drawings.ForEach(x =>
296
                {
297
                    var doc = docs.FirstOrDefault(y => y.DocumentNo.Equals(x));
298
                    if (doc != null) doc.Simularity = group.GroupNo;
299
                });
300
            }
301

    
302
            this.designDrawing.Entities.Clear();
303
            this.designDrawing.Blocks.Clear();
304
            RadMessageBox.Show("Classifying drawing is complete.");
305
        }
306

    
307
        /// <summary>
308
        /// Except Layer 폼을 띄운다.
309
        /// </summary>
310
        /// <param name="sender"></param>
311
        /// <param name="e"></param>
312
        private void RadButtonExceptLayer_Click(object sender, EventArgs e)
313
        {
314
            using(var frm = new Forms.ExceptLayer())
315
            {
316
                if(DialogResult.OK == frm.ShowDialog(this))
317
                {
318
                    string ExceptLayers = string.Join(",", Forms.ExceptLayer.ExceptLayers.Select(x => x.Name));
319
                    Classes.ID2Helper.IniWriteValue(IniFilePath, "Verification", "Except Layers", ExceptLayers);
320

    
321
                    string ExceptLayersVisible = string.Join(",", Forms.ExceptLayer.ExceptLayers.Select(x => x.Visible));
322
                    Classes.ID2Helper.IniWriteValue(IniFilePath, "Verification", "Except Layers Visible", ExceptLayersVisible);
323

    
324
                    if (Forms.ExceptLayer.TitleBlockAttribute.Any())
325
                    {
326
                        string BlockName = Forms.ExceptLayer.TitleBlockAttribute.Select(x => x.BlockName).Distinct().First();
327
                        Classes.ID2Helper.IniWriteValue(IniFilePath, "TitleBlock", "Block Name", BlockName);
328
                    }
329
                    var AttrNameList = Forms.ExceptLayer.TitleBlockAttribute.Select(x => x.AttrName).Distinct().ToList();
330
                    string Attributes = string.Join(",", AttrNameList);
331
                    Classes.ID2Helper.IniWriteValue(IniFilePath, "TitleBlock", "Attributes", Attributes);
332
                }
333
            }
334
        }
335

    
336
        /// <summary>
337
        /// 수정한 Tolerance를 시스템에 반영한다.
338
        /// </summary>
339
        /// <param name="sender"></param>
340
        /// <param name="e"></param>
341
        private void RadSpinEditorTolerance_ValueChanged(object sender, EventArgs e)
342
        {
343
            double toler = Convert.ToDouble(this.radSpinEditorTolerance.Value);
344
            Classes.ID2Helper.IniWriteValue(IniFilePath, "Verification", "Tolerance", toler.ToString());
345
            Classify.Tolerance = toler;
346
        }
347

    
348
        private void Verification_Load(object sender, EventArgs e)
349
        {
350
            string Toler = Classes.ID2Helper.IniReadValue(IniFilePath, "Verification", "Tolerance");
351
            if (!string.IsNullOrEmpty(Toler))
352
            {
353
                this.radSpinEditorTolerance.Value = Convert.ToDecimal(Toler);
354
                Classify.Tolerance = Convert.ToDouble(this.radSpinEditorTolerance.Value);
355
            }
356

    
357
            string Simularity = Classes.ID2Helper.IniReadValue(IniFilePath, "Verification", "Simularity");
358
            if (!string.IsNullOrEmpty(Simularity))
359
            {
360
                this.radSpinEditorSimularity.Value = Convert.ToDecimal(Simularity);
361
                Classify.Simularity = Convert.ToDouble(this.radSpinEditorSimularity.Value);
362
            }
363

    
364
            string _LengthToleranceRatio = Classes.ID2Helper.IniReadValue(IniFilePath, "Verification", "Length Tolerance Ratio");
365
            if (!string.IsNullOrEmpty(_LengthToleranceRatio))
366
            {
367
                LengthToleranceRatio = Convert.ToDouble(_LengthToleranceRatio);
368
            }
369

    
370
            #region Except Layer를 로딩한다.
371
            string _ExceptLayers = Classes.ID2Helper.IniReadValue(IniFilePath, "Verification", "Except Layers");
372
            if (!string.IsNullOrEmpty(_ExceptLayers))
373
            {
374
                Forms.ExceptLayer.ExceptLayers.AddRange(_ExceptLayers.Split(',').ToList().ConvertAll(x => new Forms.ExceptLayer.Layer(x)));
375

    
376
                string _ExceptLayersVisible = Classes.ID2Helper.IniReadValue(IniFilePath, "Verification", "Except Layers Visible");
377
                if (!string.IsNullOrEmpty(_ExceptLayersVisible))
378
                {
379
                    var tokens = _ExceptLayersVisible.Split(',').ToList().ConvertAll(x => Convert.ToBoolean(x));
380
                    for (int i = 0; i < Forms.ExceptLayer.ExceptLayers.Count; ++i)
381
                    {
382
                        if (i < tokens.Count)
383
                        {
384
                            Forms.ExceptLayer.ExceptLayers[i].Visible = tokens[i];
385
                        }
386
                    }
387
                }
388
            }
389
            #endregion
390

    
391
            #region Title Block 정보를 읽는다.
392
            string TitleBlockName = Classes.ID2Helper.IniReadValue(IniFilePath, "TitleBlock", "Block Name");
393
            if (!string.IsNullOrEmpty(TitleBlockName))
394
            {
395
                string Attributes = Classes.ID2Helper.IniReadValue(IniFilePath, "TitleBlock", "Attributes");
396
                if (!string.IsNullOrEmpty(Attributes))
397
                {
398
                    var tokens = Attributes.Split(',').ToList();
399
                    tokens.ForEach(x => 
400
                    {
401
                        var BlkAttr = new Forms.ExceptLayer.BlockAttribute(TitleBlockName, x);
402
                        Forms.ExceptLayer.TitleBlockAttribute.Add(BlkAttr);
403
                    });
404
                }
405
            }
406
            #endregion
407

    
408
            this.radGridViewDocument.CellDoubleClick += RadGridViewDocument_CellDoubleClick;
409
            this.radGridViewDocument.ViewRowFormatting += RadGridViewDocument_ViewRowFormatting;
410
        }
411

    
412
        private void RadGridViewDocument_ViewRowFormatting(object sender, RowFormattingEventArgs e)
413
        {
414
            if (e.RowElement is GridRowElement)
415
            {
416
                if (e.RowElement.RowInfo.DataBoundItem is Documents doc)
417
                {
418
                    string DwgFolder = System.IO.Path.Combine(informations.FindID2LocalPath(doc.RefProjectCode), "drawings", "Native");
419
                    string DocNo = doc.DocumentNo;
420
                    string FilePath = System.IO.Path.Combine(DwgFolder, $"{DocNo}{dwgExtension}");
421
                    if (!File.Exists(FilePath))
422
                    {
423
                        e.RowElement.ForeColor = Color.Gray;
424
                        e.RowElement.Font = UnmatchedFont;
425
                    }
426
                    else
427
                    {
428
                        e.RowElement.ResetValue(LightVisualElement.ForeColorProperty, ValueResetFlags.Local);
429
                        e.RowElement.Font = MatchedFont;
430
                    }
431
                }
432
            }
433
            else
434
            {
435
                e.RowElement.ResetValue(LightVisualElement.ForeColorProperty, ValueResetFlags.Local);
436
                e.RowElement.ResetValue(LightVisualElement.FontProperty, ValueResetFlags.Local);
437
            }
438
        }
439

    
440
        /// <summary>
441
        /// 더블 클릭한 도면을 연다.
442
        /// </summary>
443
        /// <param name="sender"></param>
444
        /// <param name="e"></param>
445
        private void RadGridViewDocument_CellDoubleClick(object sender, GridViewCellEventArgs e)
446
        {
447
            if (sender is GridDataCellElement CellElement)
448
            {
449
                var doc = CellElement.RowInfo.DataBoundItem as Documents;
450
                string DwgFolder = System.IO.Path.Combine(informations.FindID2LocalPath(doc.RefProjectCode), "drawings", "Native");
451
                string DocNo = doc.DocumentNo;
452
                string FilePath = System.IO.Path.Combine(DwgFolder, $"{DocNo}{dwgExtension}");
453

    
454
                if (!File.Exists(FilePath))
455
                {
456
                    RadMessageBox.Show("File doesn't exist");
457
                    return;
458
                }
459
                #region 다른 프로세스에서 파일을 열고 있는 경우 처리
460
                using (var fs = File.Open(FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
461
                #endregion
462

    
463
                {
464
                    designDrawing.Blocks.Clear();
465
                    designDrawing.Entities.Clear();
466

    
467
                    devDept.Eyeshot.Translators.ReadAutodesk ra = new devDept.Eyeshot.Translators.ReadAutodesk(fs);
468
                    ra.DoWork();
469
                    ra.AddToScene(designDrawing);
470

    
471
                    designDrawing.Invalidate();
472
                }
473
            }
474
        }
475

    
476
        /// <summary>
477
        /// 두 도면의 엔터티들을 비교한다.
478
        /// <return>차이점을 %로 리턴한다.</return>
479
        /// </summary>
480
        private double CompareDrawing(Design design, IList<Entity> FirstEntities, IList<Entity> SecondEntities)
481
        {
482
            bool[] equalEntitiesInV2 = new bool[SecondEntities.Count];
483
            var EqualIndices = new List<int>();
484

    
485
            /// 서로 검사 가능한 타입인지 확인한다.
486
            bool CheckType(Entity ent1, Entity ent2)
487
            {
488
                return ent1.GetType() == ent2.GetType() ||
489
                    (ent1.GetType() == typeof(devDept.Eyeshot.Entities.Text) && ent2.GetType() == typeof(devDept.Eyeshot.Entities.MultilineText)) ||
490
                    (ent1.GetType() == typeof(devDept.Eyeshot.Entities.MultilineText) && ent2.GetType() == typeof(devDept.Eyeshot.Entities.Text)) ||
491
                    (ent1.GetType() == typeof(devDept.Eyeshot.Entities.Line) && ent2.GetType() == typeof(devDept.Eyeshot.Entities.TabulatedSurface)) ||
492
                    (ent1.GetType() == typeof(devDept.Eyeshot.Entities.Attribute) && ent2.GetType() == typeof(devDept.Eyeshot.Entities.Text)) ||
493
                    (ent1.GetType() == typeof(devDept.Eyeshot.Entities.Attribute) && ent2.GetType() == typeof(devDept.Eyeshot.Entities.MultilineText));
494
            }
495

    
496
            int[] differents = new int[2] { 0, 0 };
497
            try
498
            {
499
                for (int i = 0; i < FirstEntities.Count(); i++)
500
                {
501
                    Entity entVp1 = FirstEntities[i];
502
                    EqualIndices.Clear();
503

    
504
                    for (int j = 0; j < SecondEntities.Count(); j++)
505
                    {
506
                        Entity entVp2 = SecondEntities[j];
507

    
508
                        if (!equalEntitiesInV2[j] && CheckType(entVp1, entVp2) && CompareIfEqual(design, entVp1, design, entVp2))
509
                        {
510
                            EqualIndices.Add(j);
511
                        }
512
                    }
513

    
514
                    #region 임계값 안에 들어오는 항목이 여러개 있을 경우 가장 가까운 항목을 유사 항목으로 선택한다.
515
                    if (EqualIndices.Any())
516
                    {
517
                        var ordered = EqualIndices.ConvertAll(x => SecondEntities[x]).OrderBy(x =>
518
                        {
519
                            return x.BoxMin.DistanceTo(entVp1.BoxMin);
520
                        });
521

    
522
                        int idx = SecondEntities.ToList().FindIndex(x => x == ordered.First());
523
                        equalEntitiesInV2[idx] = true;
524
                    }
525
                    #endregion
526

    
527
                    if (!EqualIndices.Any()) differents[0]++;
528
                }
529

    
530
                for (int j = 0; j < SecondEntities.Count; j++)
531
                {
532
                    if (!equalEntitiesInV2[j]) differents[1]++;
533
                }
534

    
535
                double a = Math.Abs(FirstEntities.Count - SecondEntities.Count) / ((FirstEntities.Count + SecondEntities.Count) * 0.5) * 100;
536
                double b = FirstEntities.Count > 0 ? ((double)differents[0] / (double)FirstEntities.Count) * 100 : 100;
537
                double c = SecondEntities.Count > 0 ? ((double)differents[1] / (double)SecondEntities.Count) * 100 : 100;
538

    
539
                return (a + b + c) / 3;
540
            }
541
            catch (Exception ex)
542
            {
543
                Console.Write($"Error : {ex.Message}");
544
            }
545

    
546
            return 100;
547
        }
548

    
549
        public void DocumentListBinding(List<ID2.Manager.Data.Models.Documents> docs)
550
        {
551
            this.radGridViewDocument.FilterDescriptors.Clear();
552
            this.radGridViewDocument.DataSource = new BindingList<ID2.Manager.Data.Models.Documents>(docs);
553
        }
554

    
555
        /// <summary>
556
        /// 주어진 두 엔터티를 비교한다.
557
        /// </summary>
558
        /// <param name="entVp1"></param>
559
        /// <param name="entVp2"></param>
560
        /// <returns></returns>
561
        private bool CompareIfEqual(Design design1, Entity entVp1, Design design2, Entity entVp2)
562
        {
563
            return AreEqual(design1, entVp1, design2, entVp2);
564
        }
565

    
566
        private bool CompareGEntityIfEqual(GEntity entVp1, GEntity entVp2)
567
        {
568
            return AreGEntityEqual(entVp1, entVp2);
569
        }
570

    
571
        /// <summary>
572
        /// 그래픽적으로 두 엔터티가 유사한지 검사한다.
573
        /// </summary>
574
        /// <param name="design1"></param>
575
        /// <param name="ent1"></param>
576
        /// <param name="design2"></param>
577
        /// <param name="ent2"></param>
578
        /// <returns></returns>
579
        private bool AreEqual(Design design1, Entity ent1, Design design2, Entity ent2)
580
        {
581
            if (ent1 is CompositeCurve cc1 && ent2 is CompositeCurve cc2)
582
            {
583
                if (cc1.CurveList.Count == cc2.CurveList.Count)
584
                {
585
                    int equalCurvesInListCount = 0;
586
                    foreach (var entC in cc1.CurveList)
587
                    {
588
                        foreach (var entC2 in cc2.CurveList)
589
                        {
590
                            if (entC.GetType() == entC2.GetType())
591
                            {
592
                                if (entC is Entity && entC2 is Entity && CompareIfEqual(design1, entC as Entity, design2, entC2 as Entity))
593
                                {
594
                                    equalCurvesInListCount++;
595
                                    break;
596
                                }
597
                                else if (entC is GEntity && entC2 is GEntity && CompareGEntityIfEqual(entC as GEntity, entC2 as GEntity))
598
                                {
599
                                    equalCurvesInListCount++;
600
                                    break;
601
                                }
602
                            }
603
                        }
604
                    }
605

    
606
                    if (cc1.CurveList.Count == equalCurvesInListCount)
607
                    {
608
                        return true;
609
                    }
610
                }
611
            }
612
            else if (ent1 is LinearPath lp1 && ent2 is LinearPath lp2)
613
            {
614
                if (lp1.Vertices.Length == lp2.Vertices.Length)
615
                {
616
                    for (int i = 0; i < lp1.Vertices.Length; i++)
617
                    {
618
                        if (lp1.Vertices[i].DistanceTo(lp2.Vertices[i]) > Classify.Tolerance)
619
                            return false;
620
                    }
621

    
622
                    return true;
623
                }
624
            }
625
            else if (ent1 is PlanarEntity && ent2 is PlanarEntity)
626
            {
627
                if (ent1 is Arc arc1 && ent2 is Arc arc2)
628
                {
629
                    if (
630
                        arc1.Center.DistanceTo(arc2.Center) <= Classify.Tolerance &&
631
                        Math.Abs(arc1.Radius - arc2.Radius) <= Classify.Tolerance &&
632
                        Math.Abs(arc1.Domain.Min - arc2.Domain.Min) <= Classify.Tolerance &&
633
                        Math.Abs(arc1.Domain.Max - arc2.Domain.Max) <= Classify.Tolerance
634
                        )
635
                    {
636
                        return true;
637
                    }
638
                }
639
                else if (ent1 is Circle c1 && ent2 is Circle c2)
640
                {
641
                    if (
642
                        c1.Center.DistanceTo(c2.Center) <= Classify.Tolerance &&
643
                        Math.Abs(c1.Radius - c2.Radius) <= Classify.Tolerance
644
                        )
645
                    {
646
                        return true;
647
                    }
648
                }
649
                else if (ent1 is EllipticalArc e1 && ent2 is EllipticalArc e2)
650
                {
651
                    if (
652
                        e1.Center.DistanceTo(e2.Center) <= Classify.Tolerance &&
653
                        Math.Abs(e1.RadiusX - e2.RadiusX) <= Classify.Tolerance &&
654
                        Math.Abs(e1.RadiusY - e2.RadiusY) <= Classify.Tolerance &&
655
                        Math.Abs(e1.Domain.Low - e2.Domain.Low) <= Classify.Tolerance &&
656
                        Math.Abs(e1.Domain.High - e2.Domain.High) <= Classify.Tolerance
657
                    )
658
                    {
659
                        return true;
660
                    }
661
                }
662
                else if (ent1 is Ellipse el1 && ent2 is Ellipse el2)
663
                {
664
                    if (
665
                        el1.Center.DistanceTo(el2.Center) <= Classify.Tolerance &&
666
                        Math.Abs(el1.RadiusX - el2.RadiusX) <= Classify.Tolerance &&
667
                        Math.Abs(el1.RadiusY - el2.RadiusY) <= Classify.Tolerance
668
                    )
669
                    {
670
                        return true;
671
                    }
672
                }
673
                #region 해치는 중점만 비교
674
                else if (ent1 is Hatch hatch1 && ent2 is Hatch hatch2)
675
                {
676
                    if (hatch1.BoxMin == null || hatch1.BoxMax == null) return false;
677
                    var center1 = (hatch1.BoxMin + hatch1.BoxMax) * 0.5;
678
                    center1.Z = 0;
679
                    if (hatch2.BoxMin == null || hatch2.BoxMax == null) return false;
680
                    var center2 = (hatch2.BoxMin + hatch2.BoxMax) * 0.5;
681
                    center2.Z = 0;
682
                    return center1.DistanceTo(center2) < Classify.Tolerance;
683
                }
684
                #endregion
685
                else if (ent1 is Text)
686
                {
687
                    if (ent1 is Dimension dim1 && ent2 is Dimension dim2)
688
                    {
689
                        if (
690
                            dim1.InsertionPoint.DistanceTo(dim2.InsertionPoint) <= Classify.Tolerance &&
691
                            dim1.DimLinePosition.DistanceTo(dim2.DimLinePosition) <= Classify.Tolerance
692
                            )
693
                        {
694
                            if (ent1 is AngularDim ad1 && ent2 is AngularDim ad2)
695
                            {
696
                                if (
697
                                    ad1.ExtLine1.DistanceTo(ad2.ExtLine1) <= Classify.Tolerance &&
698
                                    ad1.ExtLine2.DistanceTo(ad2.ExtLine2) <= Classify.Tolerance &&
699
                                    Math.Abs(ad1.StartAngle - ad2.StartAngle) <= Classify.Tolerance &&
700
                                    Math.Abs(ad1.EndAngle - ad2.EndAngle) <= Classify.Tolerance &&
701
                                    Math.Abs(ad1.Radius - ad2.Radius) <= Classify.Tolerance
702
                                    )
703
                                {
704
                                    return true;
705
                                }
706
                            }
707
                            else if (ent1 is LinearDim ld1 && ent2 is LinearDim ld2)
708
                            {
709
                                if (
710
                                    ld1.ExtLine1.DistanceTo(ld2.ExtLine1) <= Classify.Tolerance &&
711
                                    ld1.ExtLine2.DistanceTo(ld2.ExtLine2) <= Classify.Tolerance
712
                                    )
713
                                {
714
                                    return true;
715
                                }
716
                            }
717
                            else if (ent1 is DiametricDim dd1 && ent2 is DiametricDim dd2)
718
                            {
719
                                if (
720
                                    Math.Abs(dd1.Distance - dd2.Distance) <= Classify.Tolerance &&
721
                                    Math.Abs(dd1.Radius - dd2.Radius) <= Classify.Tolerance &&
722
                                    Math.Abs(dd1.CenterMarkSize - dd2.CenterMarkSize) <= Classify.Tolerance
723
                                )
724
                                {
725
                                    return true;
726
                                }
727
                            }
728
                            else if (ent1 is RadialDim rd1 && ent2 is RadialDim rd2)
729
                            {
730
                                if (
731
                                    Math.Abs(rd1.Radius - rd2.Radius) <= Classify.Tolerance &&
732
                                    Math.Abs(rd1.CenterMarkSize - rd2.CenterMarkSize) <= Classify.Tolerance
733
                                )
734
                                {
735
                                    return true;
736
                                }
737
                            }
738
                            else if (ent1 is OrdinateDim od1 && ent2 is OrdinateDim od2)
739
                            {
740
                                if (
741
                                    od1.DefiningPoint.DistanceTo(od2.DefiningPoint) <= Classify.Tolerance &&
742
                                    od1.Origin.DistanceTo(od2.Origin) <= Classify.Tolerance &&
743
                                    od1.LeaderEndPoint.DistanceTo(od2.LeaderEndPoint) <= Classify.Tolerance
744
                                )
745
                                {
746
                                    return true;
747
                                }
748
                            }
749
                            else
750
                            {
751
                                Console.Write("Type " + ent1.GetType() + " not implemented.");
752
                                return true;
753
                            }
754
                        }
755
                    }
756

    
757
                    else if (ent1 is devDept.Eyeshot.Entities.Attribute att1 && ent2 is devDept.Eyeshot.Entities.Attribute att2)
758
                    {
759
                        if (
760
                            att1.Value == att2.Value &&
761
                            att1.InsertionPoint.DistanceTo(att2.InsertionPoint) <= Classify.Tolerance
762
                            )
763
                        {
764
                            return true;
765
                        }
766
                    }
767
                    else
768
                    {
769
                        Text tx1 = (Text)ent1;
770
                        Text tx2 = (Text)ent2;
771

    
772
                        #region 대소문자, 공백을 무시하여 비교
773
                        string string1 = tx1.TextString.Trim().ToUpper();
774
                        string string2 = tx2.TextString.Trim().ToUpper();
775
                        string1 = System.Text.RegularExpressions.Regex.Replace(string1, @"\s+", "");
776
                        string2 = System.Text.RegularExpressions.Regex.Replace(string2, @"\s+", "");
777
                        if (
778
                            tx1.BoxMin.DistanceTo(tx2.BoxMin) <= Classify.Tolerance &&
779
                            string1 == string2 &&
780
                            Math.Abs(tx1.WidthFactor - tx2.WidthFactor) <= Classify.Tolerance &&
781
                            Math.Abs(tx1.Height - tx2.Height) <= Classify.Tolerance
782
                            )
783
                        {
784
                            return true;
785
                        }
786
                        #endregion
787
                    }
788
                }
789
            }
790
            else if (ent1 is Line line1 && ent2 is Line line2)
791
            {
792
                var dir1 = line1.Direction;
793
                dir1.Normalize();
794
                var dir2 = line2.Direction;
795
                dir2.Normalize();
796
                if (devDept.Geometry.Vector3D.AreParallel(dir1, dir2, 0.1) &&
797
                    Math.Abs(line1.Length() - line2.Length()) <= line1.Length() * LengthToleranceRatio &&
798
                    line1.MidPoint.DistanceTo(line2.MidPoint) <= Classify.Tolerance
799
                )
800
                {
801
                    return true;
802
                }
803
            }
804
            else if (ent1 is Line && ent2 is devDept.Eyeshot.Entities.TabulatedSurface lwpolyline && lwpolyline.ControlPoints.Length == 4)
805
            {
806
                line1 = ent1 as Line;
807
                var start = new devDept.Geometry.Point3D(lwpolyline.ControlPoints[0, 0].X, lwpolyline.ControlPoints[0, 0].Y, 0);
808
                var end = new devDept.Geometry.Point3D(lwpolyline.ControlPoints[1, 0].X, lwpolyline.ControlPoints[1, 0].Y, 0);
809
                var vec = new devDept.Geometry.Vector3D(start, end);
810
                vec.Normalize();
811
                var dir = line1.Direction.Clone() as devDept.Geometry.Vector3D;
812
                dir.Normalize();
813

    
814
                if (
815
                    devDept.Geometry.Vector3D.AreParallel(dir, vec) &&
816
                    line1.StartPoint.DistanceTo(start) <= Classify.Tolerance &&
817
                    line1.EndPoint.DistanceTo(end) <= Classify.Tolerance
818
                )
819
                {
820
                    return true;
821
                }
822
            }
823
            else if (ent1 is devDept.Eyeshot.Entities.Point point1 && ent2 is devDept.Eyeshot.Entities.Point point2)
824
            {
825
                if (point1.Position.DistanceTo(point2.Position) <= Classify.Tolerance)
826
                {
827
                    return true;
828
                }
829
            }
830
            else if (ent1 is Curve cu1 && ent2 is Curve cu2)
831
            {
832
                if (
833
                    cu1.ControlPoints.Length == cu2.ControlPoints.Length &&
834
                    cu1.KnotVector.Length == cu2.KnotVector.Length &&
835
                    cu1.Degree == cu2.Degree
836
                    )
837
                {
838
                    for (int k = 0; k < cu1.ControlPoints.Length; k++)
839
                    {
840
                        if (cu1.ControlPoints[k].DistanceTo(cu2.ControlPoints[k]) > Classify.Tolerance)
841
                        {
842
                            return false;
843
                        }
844
                    }
845

    
846
                    for (int k = 0; k < cu1.KnotVector.Length; k++)
847
                    {
848
                        if (cu1.KnotVector[k] != cu2.KnotVector[k])
849
                        {
850
                            return false;
851
                        }
852
                    }
853

    
854
                    return true;
855
                }
856
            }
857
            else if (ent1 is Mesh m1 && ent2 is Mesh m2 && m1.Vertices.Count() == m2.Vertices.Count())
858
            {
859
                for (int i = 0; i < m1.Vertices.Count(); ++i)
860
                {
861
                    if (m1.Vertices[i].DistanceTo(m2.Vertices[i]) > Classify.Tolerance) return false;
862
                }
863

    
864
                return true;
865
            }
866
            else if (ent1 is BlockReference blkref1 && ent2 is BlockReference blkref2)
867
            {
868
                int equalCurvesInEntityList = 0;
869

    
870
                #region Point, Attribute, Text 제거 및 LinePath를 라인으로 분리
871
                var entities1 = blkref1.Explode(design1.Blocks).Where(x => x.LayerName != "AS_PORT" && !(x is devDept.Eyeshot.Entities.Point) &&
872
                !(x is devDept.Eyeshot.Entities.Attribute) && !(x is devDept.Eyeshot.Entities.Text)).ToList();
873
                var coll1 = new List<Entity>();
874
                entities1.ForEach(x =>
875
                {
876
                    if (x is LinearPath lp)
877
                    {
878
                        for (int i = 0; i < lp.Vertices.Length - 1; ++i)
879
                        {
880
                            if (lp.Vertices[i].DistanceTo(lp.Vertices[i + 1]) < 0.1) continue;
881
                            coll1.Add(new Line(lp.Vertices[i], lp.Vertices[i + 1]));
882
                        }
883
                    }
884
                    else
885
                    {
886
                        coll1.Add(x);
887
                    }
888
                });
889
                #endregion
890

    
891
                #region Point 및 Nesting Block 제거 및 LinePath를 라인으로 분리
892
                var entities2 = blkref2.Explode(design2.Blocks).Where(x =>
893
                !(x is devDept.Eyeshot.Entities.BlockReference blkref && blkref.BlockName == "PORT") && !(x is devDept.Eyeshot.Entities.Point)).ToList();
894
                var coll2 = new List<Entity>();
895
                entities2.ForEach(x =>
896
                {
897
                    if (x is LinearPath lp)
898
                    {
899
                        for (int i = 0; i < lp.Vertices.Length - 1; ++i)
900
                        {
901
                            if (lp.Vertices[i].DistanceTo(lp.Vertices[i + 1]) < 0.1) continue;
902
                            coll2.Add(new Line(lp.Vertices[i], lp.Vertices[i + 1]));
903
                        }
904
                    }
905
                    else if (x is devDept.Eyeshot.Entities.Attribute attr)
906
                    {
907
                        if (!attr.Invisible) coll2.Add(attr);
908
                    }
909
                    else if (x.GetType().Name == "AttributeReferenceData")
910
                    {
911
                    }
912
                    else
913
                    {
914
                        coll2.Add(x);
915
                    }
916
                });
917
                #endregion
918

    
919
                if (coll1.Count != coll2.Count) return false;
920

    
921
                foreach (var entC in coll1)
922
                {
923
                    foreach (var entC2 in coll2)
924
                    {
925
                        if (entC.GetType() == entC2.GetType())
926
                        {
927
                            if (entC is Entity && entC2 is Entity && CompareIfEqual(design1, entC as Entity, design2, entC2 as Entity))
928
                            {
929
                                equalCurvesInEntityList++;
930
                                break;
931
                            }
932
                        }
933
                    }
934
                }
935

    
936
                if (coll1.Count == equalCurvesInEntityList)
937
                {
938
                    return true;
939
                }
940
            }
941
            else
942
            {
943
                Console.Write("Type " + ent1.GetType() + " not implemented.");
944
                return false;
945
            }
946

    
947
            return false;
948
        }
949

    
950
        private bool AreGEntityEqual(GEntity ent1, GEntity ent2)
951
        {
952
            if (ent1 is GCompositeCurve cc1 && ent2 is GCompositeCurve cc2)
953
            {
954
                if (cc1.CurveList.Count == cc2.CurveList.Count)
955
                {
956
                    int equalCurvesInListCount = 0;
957
                    foreach (var entC in cc1.CurveList)
958
                    {
959
                        foreach (var entC2 in cc2.CurveList)
960
                        {
961
                            if (entC.GetType() == entC2.GetType())
962
                            {
963
                                if (entC is GEntity && entC2 is GEntity && CompareGEntityIfEqual(entC as GEntity, entC2 as GEntity))
964
                                {
965
                                    equalCurvesInListCount++;
966
                                    break;
967
                                }
968
                            }
969
                        }
970
                    }
971

    
972
                    if (cc1.CurveList.Count == equalCurvesInListCount)
973
                    {
974
                        return true;
975
                    }
976
                }
977
            }
978
            else if (ent1 is GLinearPath lp1 && ent2 is GLinearPath lp2)
979
            {
980
                if (lp1.Vertices.Length == lp2.Vertices.Length)
981
                {
982
                    for (int i = 0; i < lp1.Vertices.Length; i++)
983
                    {
984
                        if (lp1.Vertices[i].DistanceTo(lp2.Vertices[i]) > Classify.Tolerance)
985
                            return false;
986
                    }
987
                    return true;
988
                }
989
            }
990

    
991
            else if (ent1 is GPlanarEntity pe1 && ent2 is GPlanarEntity pe2)
992
            {
993
                if (
994
                    pe1.Plane.AxisZ == pe2.Plane.AxisZ &&
995
                    pe1.Plane.AxisX == pe2.Plane.AxisX
996
                    )
997
                {
998
                    if (ent1 is GArc arc1 && ent2 is GArc arc2)
999
                    {
1000
                        if (
1001
                            arc1.Center.DistanceTo(arc2.Center) <= Classify.Tolerance &&
1002
                            Math.Abs(arc1.Radius - arc2.Radius) <= Classify.Tolerance &&
1003
                            Math.Abs(arc1.Domain.Min - arc2.Domain.Min) <= Classify.Tolerance &&
1004
                            Math.Abs(arc1.Domain.Max - arc2.Domain.Max) <= Classify.Tolerance
1005
                            )
1006
                        {
1007
                            return true;
1008
                        }
1009
                    }
1010
                    else if (ent1 is GCircle c1 && ent2 is GCircle c2)
1011
                    {
1012
                        if (c1.Center.DistanceTo(c2.Center) <= Classify.Tolerance && 
1013
                            Math.Abs(c1.Radius - c2.Radius) <= Classify.Tolerance)
1014
                        {
1015
                            return true;
1016
                        }
1017
                    }
1018
                    else if (ent1 is GEllipticalArc e1 && ent2 is GEllipticalArc e2)
1019
                    {
1020
                        if (
1021
                            e1.Center.DistanceTo(e2.Center) <= Classify.Tolerance &&
1022
                            Math.Abs(e1.RadiusX - e2.RadiusX) <= Classify.Tolerance &&
1023
                            Math.Abs(e1.RadiusY - e2.RadiusY) <= Classify.Tolerance &&
1024
                            Math.Abs(e1.Domain.Low - e2.Domain.Low) <= Classify.Tolerance &&
1025
                            Math.Abs(e1.Domain.High - e2.Domain.High) <= Classify.Tolerance
1026
                        )
1027
                        {
1028
                            return true;
1029
                        }
1030
                    }
1031
                    else if (ent1 is GEllipse el1 && ent2 is GEllipse el2)
1032
                    {
1033
                        if (
1034
                            el1.Center.DistanceTo(el2.Center) <= Classify.Tolerance &&
1035
                            Math.Abs(el1.RadiusX - el2.RadiusX) <= Classify.Tolerance &&
1036
                            Math.Abs(el1.RadiusY - el2.RadiusY) <= Classify.Tolerance
1037
                        )
1038
                        {
1039
                            return true;
1040
                        }
1041
                    }
1042
                    else
1043
                    {
1044
                        Console.Write("Type " + ent1.GetType() + " not implemented.");
1045
                        return true;
1046
                    }
1047
                }
1048
            }
1049

    
1050
            else if (ent1 is GLine line1 && ent2 is GLine line2)
1051
            {
1052
                if (line1.StartPoint.DistanceTo(line2.StartPoint) <= Classify.Tolerance && 
1053
                    line1.EndPoint.DistanceTo(line2.EndPoint) <= Classify.Tolerance
1054
                )
1055
                {
1056
                    return true;
1057
                }
1058
            }
1059
#if NURBS
1060
            else if (ent1 is Curve)
1061
            {
1062
                Curve cu1 = (Curve)ent1;
1063
                Curve cu2 = (Curve)ent2;
1064

    
1065
                if (
1066
                    cu1.ControlPoints.Length == cu2.ControlPoints.Length &&
1067
                    cu1.KnotVector.Length == cu2.KnotVector.Length &&
1068
                    cu1.Degree == cu2.Degree
1069
                    )
1070
                {
1071
                    for (int k = 0; k < cu1.ControlPoints.Length; k++)
1072
                    {
1073
                        if (cu1.ControlPoints[k] != cu2.ControlPoints[k])
1074
                        {
1075
                            return false;
1076
                        }
1077
                    }
1078

    
1079
                    for (int k = 0; k < cu1.KnotVector.Length; k++)
1080
                    {
1081
                        if (cu1.KnotVector[k] != cu2.KnotVector[k])
1082
                        {
1083
                            return false;
1084
                        }
1085
                    }
1086

    
1087
                    return true;
1088
                }
1089
            }
1090
#endif
1091

    
1092
            else
1093
            {
1094
                Console.Write("Type " + ent1.GetType() + " not implemented.");
1095
                return true;
1096
            }
1097
            return false;
1098
        }
1099
    }
1100
}
클립보드 이미지 추가 (최대 크기: 500 MB)