프로젝트

일반

사용자정보

개정판 288ed615

ID288ed6157dd8881fd046be76da3ddbb74b263a0a
상위 ad8b7f7f
하위 d72eff7a

백흠경이(가) 일년 이상 전에 추가함

Feature: 도면을 원점으로 이동시켜 비교, Compare 도면의 배경색을 검은색으로 변경

Change-Id: I1d41795c36b3c916a8039a3391151412b5476dab

차이점 보기:

ID2.Manager/ID2.Manager.Compare/Controls/Verification.cs
31 31
        private static Color AutoCADColor = Color.FromArgb(44, 44, 44);
32 32
        private static string AVEVALayer { get; } = "AVEVA";
33 33
        private static Color AVEVAColor = Color.FromArgb(44, 44, 44);
34
        private static Color DiffColor = Color.Yellow;
34
        private static string RevCloudLayer { get; } = "RevCloud";
35 35
        private static Color RevCloudColor = Color.Magenta;
36
        private static Color DiffColor = Color.Yellow;
37
        
36 38
        private static double Tolerance = 0;
37 39
        #endregion
38 40

  
......
56 58
            this.designAutoCAD.Selection.HaloOuterColor = Color.FromArgb(64, Color.OrangeRed);
57 59
            this.designAutoCAD.Selection.HaloWidthPolygons = 4;
58 60
            this.designAutoCAD.Selection.HaloWidthWires = 2;
61
            this.designAutoCAD.ActiveViewport.OriginSymbol.Visible = false;
59 62

  
60 63
            this.designAVEVA.ActionMode = actionType.SelectVisibleByPickDynamic;
61 64
            this.designAVEVA.ActiveViewport.CoordinateSystemIcon.Visible = false;
65
            this.designAVEVA.ActiveViewport.OriginSymbol.Visible = false;
62 66
            this.designCompare.ActionMode = actionType.SelectVisibleByPickDynamic;
63 67
            this.designCompare.ActiveViewport.CoordinateSystemIcon.Visible = false;
68
            this.designCompare.ActiveViewport.OriginSymbol.Visible = false;
69

  
70
            this.radCheckBoxAutoCAD.CheckStateChanged += RadCheckBoxAutoCAD_CheckStateChanged;
71
            this.radCheckBoxAVEVA.CheckStateChanged += RadCheckBoxAVEVA_CheckStateChanged;
72
            this.radCheckBoxRevCloud.CheckStateChanged += RadCheckBoxRevCloud_CheckStateChanged;
64 73

  
65 74
            _progressBar = progressBar;
66 75

  
......
87 96
            #endregion
88 97
        }
89 98

  
99
        private void RadCheckBoxRevCloud_CheckStateChanged(object sender, EventArgs e)
100
        {
101
            var layer = this.designCompare.Layers.FirstOrDefault(x => x.Name.ToUpper() == Verification.RevCloudLayer.ToUpper());
102
            if (layer != null) layer.Visible = (sender as RadCheckBox).Checked;
103
            this.designCompare.Invalidate();
104
        }
105

  
106
        private void RadCheckBoxAVEVA_CheckStateChanged(object sender, EventArgs e)
107
        {
108
            var layer = this.designCompare.Layers.FirstOrDefault(x => x.Name.ToUpper() == Verification.AVEVALayer.ToUpper());
109
            if (layer != null) layer.Visible = (sender as RadCheckBox).Checked;
110
            this.designCompare.Invalidate();
111
        }
112

  
113
        private void RadCheckBoxAutoCAD_CheckStateChanged(object sender, EventArgs e)
114
        {
115
            var layer = this.designCompare.Layers.FirstOrDefault(x => x.Name.ToUpper() == Verification.AutoCADLayer.ToUpper());
116
            if (layer != null) layer.Visible = (sender as RadCheckBox).Checked;
117
            this.designCompare.Invalidate();
118
        }
119

  
90 120
        /// <summary>
91 121
        /// Cloud Mark의 색상을 설정한다.
92 122
        /// </summary>
......
118 148
                {
119 149
                    size = new Size(1920 * 2, 1080 * 2);
120 150
                    FixedDoc = new RadFixedDocument();
151

  
152
                    designCompare.ActiveViewport.Background.BottomColor = Color.White;
153
                    designCompare.ActiveViewport.Background.TopColor = Color.White;
121 154
                }
122 155

  
123 156
                _progressBar.Maximum = docs.Count();
......
174 207
            {
175 208
                RadMessageBox.Show(ex.Message);
176 209
            }
210
            finally
211
            {
212
                designCompare.ActiveViewport.Background.BottomColor = Color.Black;
213
                designCompare.ActiveViewport.Background.TopColor = Color.Black;
214
            }
177 215
        }
178 216

  
179 217
        /// <summary>
......
277 315
                }
278 316
            }
279 317

  
280
            designCompare.ActiveViewport.Background.BottomColor = Color.White;
281
            designCompare.ActiveViewport.Background.TopColor = Color.White;
282

  
283 318
            #region Except Layer를 로딩한다.
284 319
            LoadLayerSettings();
285 320
            #endregion
......
291 326
        public void LoadLayerSettings()
292 327
        {
293 328
            Forms.ExceptLayer.ExceptLayers.Clear();
329
            Forms.ExceptLayer.LineLayers.Clear();
294 330

  
295 331
            string _ExceptLayers = Classes.ID2Helper.IniReadValue(IniFilePath, "Verification", "Except Layers");
296 332
            if (!string.IsNullOrEmpty(_ExceptLayers))
......
310 346
                    }
311 347
                }
312 348
            }
349

  
350
            string _LineLayers = Classes.ID2Helper.IniReadValue(IniFilePath, "Verification", "Line Layers");
351
            if (!string.IsNullOrEmpty(_LineLayers))
352
            {
353
                Forms.ExceptLayer.LineLayers.AddRange(_LineLayers.Split(',').ToList().ConvertAll(x => new Forms.ExceptLayer.Layer(x)));
354
            }
313 355
        }
314 356

  
315 357
        /// <summary>
......
375 417
                    {
376 418
                        devDept.Eyeshot.Translators.ReadAutodesk ra = new devDept.Eyeshot.Translators.ReadAutodesk(FilePath);
377 419
                        ra.DoWork();
420
                        var min = ra.Min;
378 421
                        if (!ra.Layers.Contains(Verification.AutoCADLayer)) ra.Layers.Add(Verification.AutoCADLayer, Verification.AutoCADColor);
379 422
                        foreach (var ent in ra.Entities)
380 423
                        {
381
                            ent.Color = Verification.AutoCADColor;
382
                            ent.ColorMethod = colorMethodType.byEntity;
383
                            if (!Forms.ExceptLayer.ExceptLayers.Exists(x => x.Name.ToUpper() == ent.LayerName.ToUpper()))
384
                            {
385
                                ent.LayerName = Verification.AutoCADLayer;
386
                            }
424
                            /// 도면을 원점으로 맞춘다.
425
                            ent.Translate(-min.X, -min.Y);
387 426
                        }
388 427
                        ra.AddToScene(design);
389 428
                    }
......
394 433
                    }
395 434

  
396 435
                    var AddEntities = new List<Entity>();
397
                    design.Entities.Where(x => x.LayerName == Verification.AutoCADLayer).ToList().ForEach(x =>
436
                    #region LinearPath를 Line으로 분할한다.
437
                    design.Entities.ForEach(x =>
398 438
                    {
399 439
                        if (x is LinearPath lp)
400 440
                        {
......
409 449
                                });
410 450
                            }
411 451
                        }
412
                        else if (x is BlockReference blkref && blkref.Attributes.Any())
413
                        {
414
                            var attributes = blkref.Attributes;
415
                            var entities = blkref.Explode(design.Blocks);
416
                            foreach (var ent in entities.Where(y => y is devDept.Eyeshot.Entities.Attribute))
417
                            {
418
                                var txt = ent as devDept.Eyeshot.Entities.Attribute;
419
                                txt.LayerName = Verification.AutoCADLayer;
420
                                KeyValuePair<string, AttributeReference>? kp = attributes.FirstOrDefault(z => z.Key == txt.TextString);
421
                                if (kp.HasValue) txt.TextString = (kp.Value.Value) != null ? kp.Value.Value.Value : string.Empty;
422
                            }
423

  
424
                            AddEntities.AddRange(entities.Where(y => 
425
                            {
426
                                if (y is devDept.Eyeshot.Entities.Attribute attr && !string.IsNullOrEmpty(attr.TextString)) return true;
427
                                if (y is devDept.Eyeshot.Entities.Text text && !string.IsNullOrEmpty(text.TextString)) return true;
428
                                return false;
429
                            }));
430
                            blkref.Attributes.Clear();
431
                            blkref.UpdateBoundingBox(new TraversalParams(design));
432
                        }
433 452
                    });
434

  
435
                    #region LinearPath 그리고 Except Layer에 있고 Visible=False 항목 제외
436
                    design.Entities.RemoveAll(x => (x is LinearPath && x.LayerName == Verification.AutoCADLayer) || 
437
                    Forms.ExceptLayer.ExceptLayers.Exists(y => y.Name.ToUpper() == x.LayerName.ToUpper() && !y.Visible));
438
                    #endregion
453
                    design.Entities.RemoveAll(x => (x is LinearPath));
439 454
                    design.Entities.AddRange(AddEntities);
455
                    #endregion
440 456

  
441
                    #region 브랜치가 생성되는 부분에서 라인을 분할
442
                    var queue = design.Entities.Where(x => x is Line && x.LayerName == Verification.AutoCADLayer).ToList();
457
                    #region 브랜치가 생성되는 부분에서 파이프 라인을 분할
458
                    var queue = design.Entities.Where(x => x is Line && 
459
                    Forms.ExceptLayer.LineLayers.Exists(y => y.Name.ToUpper() == x.LayerName.ToUpper())).ToList();
443 460
                    while (queue.Any())
444 461
                    {
445 462
                        var line1 = queue.First() as Line;
......
508 525
                    }
509 526
                    #endregion
510 527

  
528
                    #region 레이어 변경
529
                    foreach (var ent in design.Entities)
530
                    {
531
                        ent.Color = Verification.AutoCADColor;
532
                        ent.ColorMethod = colorMethodType.byEntity;
533
                        if (!Forms.ExceptLayer.ExceptLayers.Exists(x => x.Name.ToUpper() == ent.LayerName.ToUpper()))
534
                        {
535
                            ent.LayerName = Verification.AutoCADLayer;
536
                        }
537
                    }
538
                    #endregion
539

  
540
                    #region 블록을 깸
541
                    AddEntities.Clear();
542
                    design.Entities.Where(x => x.LayerName == Verification.AutoCADLayer).ToList().ForEach(x =>
543
                    {
544
                        if (x is BlockReference blkref)
545
                        {
546
                            var entities = blkref.Explode(design.Blocks);
547
                            foreach (var ent in entities) ent.LayerName = Verification.AutoCADLayer;
548
                            entities.ToList().ForEach(y =>
549
                            {
550
                                if (y is LinearPath lp)
551
                                {
552
                                    int count = Convert.ToInt32(lp.Vertices.Length);
553
                                    for (int i = 0; i < count - 1; ++i)
554
                                    {
555
                                        var line = new devDept.Eyeshot.Entities.Line(lp.Vertices[i], lp.Vertices[i + 1])
556
                                        {
557
                                            LayerName = lp.LayerName,
558
                                            LineWeight = lp.LineWeight,
559
                                            LineTypeMethod = colorMethodType.byEntity,
560
                                            Color = Verification.AutoCADColor,
561
                                            ColorMethod = colorMethodType.byEntity
562
                                        };
563
                                        AddEntities.Add(line);
564
                                    }
565
                                }
566
                            });
567

  
568
                            var attributes = blkref.Attributes;
569
                            foreach (var ent in entities.Where(y => y is devDept.Eyeshot.Entities.Attribute))
570
                            {
571
                                var txt = ent as devDept.Eyeshot.Entities.Attribute;
572
                                txt.LayerName = Verification.AutoCADLayer;
573
                                txt.Color = Verification.AutoCADColor;
574
                                txt.ColorMethod = colorMethodType.byEntity;
575
                                KeyValuePair<string, AttributeReference>? kp = attributes.FirstOrDefault(z => z.Key == txt.TextString);
576
                                if (kp.HasValue) txt.TextString = (kp.Value.Value) != null ? kp.Value.Value.Value : string.Empty;
577
                            }
578

  
579
                            AddEntities.AddRange(entities.Where(y => 
580
                            {
581
                                if (y is devDept.Eyeshot.Entities.Attribute attr && string.IsNullOrEmpty(attr.TextString)) return false;
582
                                if (y is devDept.Eyeshot.Entities.Text text && string.IsNullOrEmpty(text.TextString)) return false;
583
                                if (y is LinearPath) return false;
584
                                return true;
585
                            }));
586

  
587
                            blkref.Attributes.Clear();
588
                            blkref.UpdateBoundingBox(new TraversalParams(design));
589
                        }
590
                    });
591

  
592
                    design.Entities.RemoveAll(x => (x is BlockReference) || Forms.ExceptLayer.ExceptLayers.Exists(y => y.Name.ToUpper() == x.LayerName.ToUpper() && !y.Visible));
593
                    design.Entities.AddRange(AddEntities);
594
                    #endregion
595

  
511 596
                    ColorEntities(design, design.Entities, Verification.AutoCADColor);
512 597

  
513 598
                    // Sets the view as Top
......
525 610
                {
526 611
                    devDept.Eyeshot.Translators.ReadAutodesk ra = new devDept.Eyeshot.Translators.ReadAutodesk(FilePath);
527 612
                    ra.DoWork();
613
                    var min = ra.Min;
614
                    var AddEntities = new List<Entity>();
615

  
528 616
                    if (!ra.Layers.Contains(Verification.AVEVALayer)) ra.Layers.Add(Verification.AVEVALayer, Verification.AVEVAColor);
529 617
                    foreach (var ent in ra.Entities)
530 618
                    {
531
                        ent.Color = Verification.AVEVAColor;
532
                        ent.ColorMethod = colorMethodType.byEntity;
533
                        if (!Forms.ExceptLayer.ExceptLayers.Exists(x => x.Name.ToUpper() == ent.LayerName.ToUpper()))
534
                        {
535
                            ent.LayerName = Verification.AVEVALayer;
536
                        }
537
                    }
538
                    ra.AddToScene(design);
619
                        /// 도면을 원점으로 맞춘다.
620
                        ent.Translate(-min.X, -min.Y);
539 621

  
540
                    #region 멀티 라인들을 분할하여 추가한다.
541
                    var AddEntities = new List<Entity>();
542
                    design.Entities.Where(x => x.LayerName == Verification.AVEVALayer).ToList().ForEach(x =>
543
                    {
544
                        if (x is Mesh mesh && (mesh.LayerName == "AS_PIPE" || mesh.LayerName == "AS_INST"))
622
                        #region 멀티 라인들을 분할하여 추가한다.
623
                        if (ent is Mesh mesh && (mesh.LayerName == "AS_PIPE" || mesh.LayerName == "AS_INST"))
545 624
                        {
546 625
                            int count = Convert.ToInt32(mesh.Vertices.Length * 0.5);
547 626
                            for (int i = 0; i < count - 1; ++i)
548 627
                            {
549 628
                                AddEntities.Add(new devDept.Eyeshot.Entities.Line(mesh.Vertices[i], mesh.Vertices[i + 1])
550 629
                                {
551
                                    LayerName = mesh.LayerName,
630
                                    LayerName = Verification.AVEVALayer,
552 631
                                    LineWeight = 3.0f,
553 632
                                    LineTypeMethod = colorMethodType.byEntity,
554 633
                                    Color = Verification.AVEVAColor,
......
556 635
                                });
557 636
                            }
558 637
                        }
559
                        else if (x is TabulatedSurface tf && (tf.LayerName == "AS_PIPE" || tf.LayerName == "AS_INST"))
638
                        else if (ent is TabulatedSurface tf && (tf.LayerName == "AS_PIPE" || tf.LayerName == "AS_INST"))
560 639
                        {
561 640
                            int count = Convert.ToInt32(tf.ControlPoints.Length * 0.5);
562 641
                            for (int i = 0; i < count - 1; ++i)
......
566 645
                                    new devDept.Geometry.Point3D(tf.ControlPoints[i, 0].X, tf.ControlPoints[i, 0].Y, 0),
567 646
                                    new devDept.Geometry.Point3D(tf.ControlPoints[i + 1, 0].X, tf.ControlPoints[i + 1, 0].Y, 0))
568 647
                                    {
569
                                        LayerName = tf.LayerName,
648
                                        LayerName = Verification.AVEVALayer,
570 649
                                        LineWeight = 3.0f,
571 650
                                        LineTypeMethod = colorMethodType.byEntity,
572 651
                                        Color = Verification.AVEVAColor,
......
575 654
                                );
576 655
                            }
577 656
                        }
578
                        else if (x is LinearPath lp)
657
                        else if (ent is LinearPath lp)
579 658
                        {
580 659
                            int count = Convert.ToInt32(lp.Vertices.Length);
581 660
                            for (int i = 0; i < count - 1; ++i)
582 661
                            {
583 662
                                AddEntities.Add(new devDept.Eyeshot.Entities.Line(lp.Vertices[i], lp.Vertices[i + 1])
584 663
                                {
585
                                    LayerName = lp.LayerName,
664
                                    LayerName = Verification.AVEVALayer,
586 665
                                    LineWeight = lp.LineWeight,
666
                                    Color = Verification.AVEVAColor,
587 667
                                    LineTypeMethod = colorMethodType.byEntity
588 668
                                });
589 669
                            }
590 670
                        }
591
                        else if(x is BlockReference blkref)
671
                        #endregion
672

  
673
                        ent.Color = Verification.AVEVAColor;
674
                        ent.ColorMethod = colorMethodType.byEntity;
675
                        if (!Forms.ExceptLayer.ExceptLayers.Exists(x => x.Name.ToUpper() == ent.LayerName.ToUpper()))
676
                        {
677
                            ent.LayerName = Verification.AVEVALayer;
678
                        }
679
                    }
680
                    ra.AddToScene(design);
681

  
682
                    #region 블럭을 깸
683
                    design.Entities.Where(x => x.LayerName == Verification.AVEVALayer).ToList().ForEach(x =>
684
                    {
685
                        if(x is BlockReference blkref)
592 686
                        {
593 687
                            var attributes = blkref.Attributes;
594 688
                            var entities = blkref.Explode(design.Blocks);
689
                            entities.ToList().ForEach(y =>
690
                            {
691
                                if (y is LinearPath lp)
692
                                {
693
                                    int count = Convert.ToInt32(lp.Vertices.Length);
694
                                    for (int i = 0; i < count - 1; ++i)
695
                                    {
696
                                        var line = new devDept.Eyeshot.Entities.Line(lp.Vertices[i], lp.Vertices[i + 1])
697
                                        {
698
                                            LayerName = Verification.AVEVALayer,
699
                                            LineWeight = lp.LineWeight,
700
                                            LineTypeMethod = colorMethodType.byEntity,
701
                                            Color = Verification.AVEVAColor,
702
                                            ColorMethod = colorMethodType.byEntity
703
                                        };
704
                                        AddEntities.Add(line);
705
                                    }
706
                                }
707
                                else
708
                                {
709
                                    y.LayerName = Verification.AVEVALayer;
710
                                    y.Color = Verification.AVEVAColor;
711
                                    y.ColorMethod = colorMethodType.byEntity;
712
                                }
713
                            });
714

  
595 715
                            foreach (var ent in entities.Where(y => y is devDept.Eyeshot.Entities.Attribute))
596 716
                            {
597 717
                                var txt = ent as devDept.Eyeshot.Entities.Attribute;
598 718
                                txt.LayerName = Verification.AVEVALayer;
719
                                txt.Color = Verification.AVEVAColor;
720
                                txt.ColorMethod = colorMethodType.byEntity;
599 721
                                KeyValuePair<string, AttributeReference>? kp = attributes.FirstOrDefault(z => z.Key == txt.TextString);
600 722
                                if (kp.HasValue) txt.TextString = (kp.Value.Value) != null ? kp.Value.Value.Value : string.Empty;
601 723
                            }
602 724

  
603 725
                            AddEntities.AddRange(entities.Where(y =>
604 726
                            {
605
                                if (y is devDept.Eyeshot.Entities.Attribute attr && !string.IsNullOrEmpty(attr.TextString)) return true;
606
                                if (y is devDept.Eyeshot.Entities.Text text && !string.IsNullOrEmpty(text.TextString)) return true;
607
                                return false;
727
                                if (y is devDept.Eyeshot.Entities.Attribute attr && string.IsNullOrEmpty(attr.TextString)) return false;
728
                                if (y is devDept.Eyeshot.Entities.Text text && string.IsNullOrEmpty(text.TextString)) return false;
729
                                if (y is LinearPath) return false;
730
                                return true;
608 731
                            }));
609 732
                            blkref.Attributes.Clear();
610 733
                            blkref.UpdateBoundingBox(new TraversalParams(design));
611 734
                        }
612 735
                    });
613 736
                    design.Entities.RemoveAll(x =>
614
                    ((x is Mesh || x is TabulatedSurface) && (x.LayerName == "AS_PIPE" || x.LayerName == "AS_INST")) ||
615
                    (x is LinearPath && x.LayerName == Verification.AVEVALayer) ||
737
                    ((x is Mesh || x is TabulatedSurface) && (x.LayerName == Verification.AVEVALayer)) ||
738
                    (x is LinearPath && x.LayerName == Verification.AVEVALayer) || (x is BlockReference) ||
616 739
                    Forms.ExceptLayer.ExceptLayers.Exists(y => y.Name.ToUpper() == x.LayerName.ToUpper() && !y.Visible));
617 740
                    design.Entities.AddRange(AddEntities);
618 741
                    #endregion
......
654 777
                var AutoCADEntities = this.designCompare.Entities.Where(x => x.LayerName == Verification.AutoCADLayer).ToList();
655 778
                var AVEVAtities = this.designCompare.Entities.Where(x => x.LayerName == Verification.AVEVALayer).ToList();
656 779
                CompareAndMark(this.designCompare, AutoCADEntities, this.designCompare, AVEVAtities);
780
                this.designCompare.Entities.ForEach(x => 
781
                {
782
                    if (x.LayerName != Verification.AVEVALayer && x.LayerName != Verification.AutoCADLayer &&
783
                    x.LayerName != Verification.RevCloudLayer) x.LayerName = Verification.AutoCADLayer;
784
                });
657 785
            }
658 786
        }
659 787

  
......
698 826
                            equalEntitiesInV1[j] = i;
699 827
                            equalEntitiesInV2[j] = true;
700 828
                            foundEqual = true;
829

  
830
                            design2.Entities.Remove(entVp2);
701 831
                            break;
702 832
                        }
703 833
                    }
......
771 901
                }
772 902
                #endregion
773 903

  
904
                if (!design2.Layers.Contains(Verification.RevCloudLayer))
905
                    design2.Layers.Add(Verification.RevCloudLayer.ToUpper(), Verification.RevCloudColor);
774 906
                DiffRegions.ForEach(x => DrawRevCloud(design2, x));
775 907
            }
776 908
            catch(Exception ex)
......
835 967
            }
836 968

  
837 969
            var revcloud = new devDept.Eyeshot.Entities.CompositeCurve(profile);
838
            revcloud.LayerName = "AVEVA";
970
            revcloud.LayerName = Verification.RevCloudLayer;
839 971
            revcloud.Color = Verification.RevCloudColor;
840 972
            revcloud.ColorMethod = colorMethodType.byEntity;
841 973
            design.Entities.Add(revcloud);
......
962 1094
                #region 해치는 삽입점만 비교
963 1095
                else if (ent1 is Hatch hatch1 && ent2 is Hatch hatch2)
964 1096
                {
965
                    return hatch1.PatternOrigin.DistanceTo(hatch2.PatternOrigin) < Verification.Tolerance;
1097
                    var center1 = (hatch1.BoxMin + hatch1.BoxMax) * 0.5;
1098
                    center1.Z = 0;
1099
                    var center2 = (hatch2.BoxMin + hatch2.BoxMax) * 0.5;
1100
                    center2.Z = 0;
1101
                    return center1.DistanceTo(center2) < Verification.Tolerance;
966 1102
                }
967 1103
                #endregion
968 1104
                else if (ent1 is Text)
......
1077 1213
                var dir2 = line2.Direction;
1078 1214
                dir2.Normalize();
1079 1215
                if (devDept.Geometry.Vector3D.AreParallel(dir1, dir2, 0.1) &&
1080
                    Math.Abs(line1.Length() - line2.Length()) <= Verification.Tolerance &&
1216
                    Math.Abs(line1.Length() - line2.Length()) <= 0.1 &&
1081 1217
                    line1.MidPoint.DistanceTo(line2.MidPoint) <= Verification.Tolerance
1082 1218
                )
1083 1219
                {

내보내기 Unified diff

클립보드 이미지 추가 (최대 크기: 500 MB)