読者です 読者をやめる 読者になる 読者になる

C#ATIA

↑タイトル詐欺 主にCATIA V5 の VBA

Viewに基準線を入れる2

こちらの続きです。
Viewに基準線を入れる1 - C#ATIA
C#化しました。 相変わらず大げさなコードです。

//cs
namespace Drw_Abs_Line {
    using System.Linq;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;//COMオブジェクトを操作するために必要
    using DRAFTINGITF;//Catiaのライブラリ
    using INFITF;//Catiaのライブラリ
    using MECMOD;//Catiaのライブラリ
    using System.Collections.Generic;

    static class Program {
        static void Main() {
            var catia = (INFITF.Application)Marshal
                        .GetActiveObject("CATIA.Application");
            var AbsLine = new Create_Abs_Line(catia);
            AbsLine.Execute();
        }
    }

    class Create_Abs_Line {
        public Create_Abs_Line(INFITF.Application Catia) {
            CatHelper.State = new CatiaContainer(Catia);
        }

        public void Execute() {
            if (CatHelper.State.Views.Count < 3) { return; }
            var StartView = CatHelper.State.Views.ActiveView;
            foreach (var view in CatHelper.State.ViewsEnumerable
                                 .Where((v, index) => index > 1)) {
                if (!view.IsAbsLine()) {
                    CatHelper.State.View = view;
                    view.Activate();
                    CatHelper.Create_Line(-20d, 0d, 20d, 0d);
                    CatHelper.Create_Line(0d, -20d, 0d, 20d);
                }
            }
            StartView.Activate();
        }
    }

    class CatiaContainer {
        private INFITF.Application catia;

        public CatiaContainer(INFITF.Application cat) {
            Catia = cat;
            Setting();
        }

        ~CatiaContainer() {
            if (catia != null) { Marshal.ReleaseComObject(catia); }
        }

        public void Setting() {
            DrawDoc = catia.ActiveDocument as DrawingDocument;
            Views = DrawDoc.Sheets.ActiveSheet.Views;
            Selection = DrawDoc.Selection;
        }

        public INFITF.Application Catia {
            get {
                return catia;
            }
            private set {
                catia = value;
            }
        }
        public DrawingDocument DrawDoc { get; private set; }
        public DrawingViews Views { get; private set; }
        public Selection Selection { get; private set; }
        public IEnumerable<DrawingView> ViewsEnumerable {
            get {
                return Enumerable.Range(1, Views.Count)
                                 .Select(i => Views.Item(i));
            }
        }
        public DrawingView View { get; set; }
        public Factory2D Fac2D {
            get {
                return View.Factory2D;
            }
        }
    }

    static class CatHelper {
        public static CatiaContainer State { get; set; }

        public static void Create_Line(double x1, double y1, double x2, double y2) {
            var L2D = State.Fac2D.CreateLine(x1, y1, x2, y2);
            State.Selection.Clear();
            State.Selection.Add(L2D);
            State.Selection.VisProperties.SetRealLineType(4, 0);
            State.Selection.VisProperties.SetRealWidth(1, 0);
            State.Selection.Clear();
            L2D.set_Name("Abs_Line");
        }

        public static bool IsAbsLine(this DrawingView vi) {
            foreach (GeometricElement Geo in vi.GeometricElements) {//①
                if (Geo.get_Name() == "Abs_Line") { return true; }
            }
            return false;
        }
    }
}

Create_Abs_LineクラスのViewsの回り方と、CatiaContainerクラスは
こちらをほぼ流用。
Viewのロック・アンロック2 - C#ATIA
CatHelperクラスはVBAのCreate_Line・IsAbsLineメソッドを積んだのみ
となっています。

①:LinqのAnyメソッドを使用すると1行で書けるのですが、
  素直にforeachにしました。Linqだとこんな感じです。

//cs
        public static bool IsAbsLine(this DrawingView vi) {
            return Enumerable.Range(1, vi.GeometricElements.Count)
                             .Select(Geo => vi.GeometricElements.Item(Geo))
                             .Any(Geo => Geo.get_Name() == "Abs_Line");
        }

こっちの方がカッコいいかも。
「Range」と「Select」はCOMのコレクションでLinqを使用するための準備なので、
実質「Any」だけですね。 そう考えると、こちらの最後の方にも記載した

Viewのロック・アンロック2 - C#ATIA
ToEnumerable<T>のようなジェネリックメソッドが欲しいところ。
オブジェクト名でイチイチ判断するのも面倒なため、
リフレクションで「Count」や「Add」の有無で判断しdynamic型で・・・
とも思ったのですが、Selectionクラスだけが他のコレクションと
挙動が違うので・・・。それだけ別処理されるのもアリかな?