วันพุธที่ 23 กันยายน พ.ศ. 2563

การใช้คำสั่งNosql Mongodb แบบง่ายๆ

 Mongodb เป็น Database NoSQL ที่นิยมที่สุดในปัจจุบัน มีทั้ง Free และเสียเงิน การติดตั้ง ทำได้ง่ายมาก สามารถติดตั้งใน Web ได้ ทันที โดยไปที่ 

https://docs.mongodb.com/manual/administration/install-community/

และการติดตั้ง ต้องติดตั้ง Command line Tool ด้วย 


สำหรับ การ เรียกใช้ หรือสร้าง database ใชัคำสั่ง use

use test

เป็นต้น

สำหรบ Table จะไม่มี mongodb เรียก collection 

db.createCollection("sampledata")

db.sampledata.insert({ id:1,name:"hello"})


วิธี Query

db.sampledata.find() เป็นการค้นทังหมด และ กด it แสดงต่อ

db.sampledata.find({id:2},{name:1}) เป็นการค้นหา id=2 และแสดง ค่า



วันพุธที่ 26 สิงหาคม พ.ศ. 2563

การติดต่อ ระหว่าง Gridview ของ C# form กับ C# Asp Web

ในการส่ง Data ระหว่าง Gridview 2 ระบบโดยเฉพาะ ระบบใหม่มักจะเป็น REST เพื่อความง่าย จะส่ง ผ่านกันทาง Json Format ที่เป็น String และมี {}

ในการส่าง Data ของ Gridview จะส่งโดยตรงไม่ได้ ต้องส่งทาง Datasource เช่นใน Window Form ต้องส่งเป็น Datatable แทน

  DataTable dt = new DataTable();

            foreach (DataGridViewColumn col in dgvReport.Columns)

            {

                dt.Columns.Add(col.Name);

            }


            foreach (DataGridViewRow row in dgvReport.Rows)

            {

                DataRow dRow = dt.NewRow();

                foreach (DataGridViewCell cell in row.Cells)

                {

                    dRow[cell.ColumnIndex] = cell.Value;

                }

                dt.Rows.Add(dRow);

            }

            var js = Newtonsoft.Json.JsonConvert.SerializeObject(dt);

            //  MessageBox.Show(js.ToString());

            File.WriteAllText("c:/temp/v.json",js.ToString());


สำหรับใน Web form ก็จะรับได้ ในแบบ เดียวกัน แต่ต้องมี Option ในการ convert ว่าเป็น Datatable เหมือนกัน

   string myDynamicJSON = File.ReadAllText("c:/temp/v.json");

        //Using dynamic keyword with JsonConvert.DeserializeObject, here you need to import Newtonsoft.Json  

        dynamic myObject = (DataTable)JsonConvert.DeserializeObject(myDynamicJSON, typeof(DataTable));

        


        //Binding gridview from dynamic object   

        GridView1.DataSource = myObject;

        GridView1.DataBind();

วันอังคารที่ 4 สิงหาคม พ.ศ. 2563

Setup Nodejs เป็น Simple http server

NodeJs เป็น ระบบ Webserver ที่ง่าย และ นิยมมากใช้ Javascript เป็น Client และ Server ตัวอย่างของ Forge Viewer จะเป็น NodeJs เสียส่วนใหญ่ 

การติดตั้ง เข้า Directory ก่อน เช่น c:\test

1. Init ก่อน
    npm init
    ตั้งค่า project ตามที่แนะนำ ใส่ชื่อ โครง การ Version และ file main ให้ เป็น server.js
2. สร้างหรือแก้ server.js

var connect = require('connect');

var serveStatic = require('serve-static');


connect()

    .use(serveStatic(__dirname))

    .listen(8080, () => console.log('Server running on 8080...'));


3.ติดตั้ง Package 

  npm install connect serve-static

4.run

  npm run start


Server ก็จะไปอยู่ ที่ 

http://localhost:8080

โดยที่จะ Default เป็น index.js หรือ index.html


Autodesk Forge การใช้ Markups

การใช้ Markups ใน Autodesk Forge 
มี 2 จุด ต้องแก้ที่ Index.html ให้ ใช้ viewer3D.js ต้องระวัง อย่างใช้ viewer3d.min.js ตัวนี้จะเป็นตัว Light
สามารถทำได้ โดย เพิ่ม Extension
ใน ForgeViewer.js

 var config3d = {

        extensions: ['Autodesk.Sample.CustomPropertyPanelExtension',  'Autodesk.Viewing.MarkupsCore', 'Autodesk.Viewing.MarkupsGui']

    };

    viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer'), config3d);


    viewer.start();

วันอาทิตย์ที่ 5 กรกฎาคม พ.ศ. 2563

การใช้ Forge Viewer กับ Visual Studio

การใช้งาน Forge Viewer น่าจะเป็นส่วนที่ใช้งานได้ ดีที่สุด และ ไม่ยากเกินไปในการทำความเข้าใจ ก่อนอื่น ต้องเข้าใจความสัมพันธ์ ของ Forge Viewer กับส่วนอื่นก่อน


Forge Viewer จะ สัมพันธ์ กับ Model Derivative และ Datamangement เนื่องจาก Viewer จะแสดงผลจาก Datastorage ชั่วคราว(ซึงแน่นอน ต้องมี Account ที่ Autodesk.com) จาก Server ของ Autodesk และ การแปลงไฟล์ จะใช้ Model Derivative  จัดการบางส่วน. Format ที่แสดงใน Forge Viewer จะเป็น SVF บน HTML5

การแสดง ผลของ Forge Viewer ถูกออกแบบมาให้ง่ายที่สุดโดยเป็น HTML+Javascript
ตัวอย่าง สามารถทำตาม Tutorial นี้ ได้
https://forge.autodesk.com/en/docs/viewer/v2/tutorials/basic-viewer/

แต่ กรณีที่จะทำ Application และ เข้าใจได้มากกว่าให้ download ตัวอย่างนี้ จะเข้าใจได้ดีกว่า โดยเป็น Desktop Application แต่ เจาะช่องต่อกับ Forge Viewer ใน Browser จะมีขอดีคือ Debug ได้

https://github.com/Autodesk-Forge/forge-bucketsmanager-desktop


ซึ่งจะอธิบายต่อไป

วันจันทร์ที่ 15 มิถุนายน พ.ศ. 2563

Forge เป็น ระบบ BIM บน Cloud

Autodesk Forge เป็นระบบ การ ทำงาน CAD+BIM ในระบบ Cloud บริษัท Autodesk ผู้ผลิต Autocad และ Revit ได้เสนอ ระบบ การทำงาน CAD,BIM บน  Internet Cloud โดยระบบของ Autodesk Forge จะเน้นการทำงาน Custom Application CAD ในรูปแบบของ OEM ทำให้ ผู้ที่พัฒนาโปรแกรม CAD หรือ BIM สามารถให้บริการกับลูกค้าได้ โดย Autodesk เป็นผุ้ Provide service อยู่ ข้างหลัง เป้าหมาย ของ Autodesk คือให้ บริการ Forge เข้าทดแทนระบบ Desktop ให้ได้ในปี 2023 ตาม SAS(Software as Service เหมือน google , facebook)
  ความน่าสนใจของระบบ Forge คือ
1.ไม่ต้องลงโปรแกรมใช้ Browser ใน iPad,Android,Windows,Osx ขอให้เป็น Browser ที่ support javascript 
2.ให้บริการกับ CAD,BIM หลากหลาย มากไม่จำเป็นต้องเฉพาะของ Autodesk โดยบริการของ Forge สามารถทำงานกับ Solidwork, ProEngineer, Sketckup. และ
3, ที่สำคัญที่สุด คือ ค่าบริการ ซึ่งในตอนนี้ จะเป็นช่วงที่ แนะนำให้ใช้ ในหลายบริการมีค่าบริการตำมาก เช่น Viewer แทบจะไม่ได้คิดราคา ดังนั้น จึงน่าสนใจสำหรับ ผุ้ใช้งานเช่น BIM ในการส่งต่อหรือ Co-operate งาน เมื่อเทียบกับค่า Subscription ของ Revit

Autodesk Forge Service แบ่งเป็น  8 หมวดงาน  ส่วนที่ไม่ได้แสดงในรูปคือ Forge Viewer



Forge Viewer. เป็นตัวแสดงรูปภาพ Model ใน File format ต่างๆ เช่น Dwg, Sketchup, Revit, Solidwork เป็นต้น และ สามารถ จัดการ Element ต่างๆได้เช่น การ เปลี่ยน Material หรือ แก้ไขสีเส้นต่างๆ

BIM360 API เป็นการเข้าไปดึงข้อมูลการจัดการของ BIM360 Account Security ของ user

Data Management API เป็นการจัดการ File Data ของ A360 , BIM360

Design Automation API เป็นการ ให้ โปรแกรม ใน Cloud ทำงาน เช่น การ Extract data จาก ไฟล์ Revit ออกมาเป็น Worksheet โดยทำงานในลักษณะ Batch สั่งจาก Cloud โดยสามารถทำได้ในทุก product เช่น Autocad,Revit,Inventor และ 3DMax

Model Derivative API เป็นระบบ Convert แปลงเป็น ไฟล์ ต่างๆ

Reality Capture API เป็น ระบบ Scan 3D

Token Flex Usage Data API เป็นระบบ บัญชีการคิด CPU Time สามารถกระจายตาม Service ต่างๆทีต้องการ คิดได้

Web Hook API เป็นระบบแจ้ง การใช้งานบริการต่างๆ ของ Autodesk โดยส่ง Event มาที่ Web ของ Developer

ผู้ที่ต้องการใช้งาน Forge ลงทะเบียนได้ Free ควรจะมีความเข้าใจกับ Javascript พอสมควร

Reference:
forge.autodesk.com










วันพุธที่ 13 พฤษภาคม พ.ศ. 2563

การสร้าง Form ใน Python

Python มี tool ดีๆ มาก แต่มักจะเป็น Command line จะให้มี User Interface มี Tool ที่ง่ายๆ ได้แก่ tkinter

วิธีใช้
ใช่ messagebox

from tkinter import messagebox

messagebox.showinfo('Title','hello world')


จะแสดงเป็น Message box



ถ้าต้องการ Form และมี Response

from tkinter import *
from tkinter import messagebox
from tkinter import ttk
window = Tk()
window.title("Welcome to TutorialsPoint")
window.geometry('400x400')
lName = Label(window ,text = "Name").grid(row = 0,column = 0)
name = Entry(window,width=10)
name.grid(row = 0,column = 1)
def clicked():
  messagebox.showinfo('ok',name.get())
btn = ttk.Button(window ,text="Submit",command=clicked).grid(row=4,column=0)
window.mainloop()

สังเกตุที่ def clicked() จะเป็น Event ใน ttk.Button
เมื่อกดจะเกิด Pop up





วันอังคารที่ 14 เมษายน พ.ศ. 2563

การสร้าง Dynamo Dropdown Node

Dropdown  Node ของ Dynamo ทำให้ผู้ใช้งาน ง่ายขึ้นในการเลือก Option ต่างๆ แต่การสร้าง ต้องทำเป็น Class คนละวิธีกับ การสร้าง Function Node ข้อแนะนำควรจะใช้ Dynamo Engine 2 และจำเป็นต้องวาง packages และ bin ใน Folder Default ของ Dynamo เท่านั้น ไม่นั้น จะไม่ทำงาน

จะมี องค์ประกอบ ได้แก่ Class ที่ต้อง Inherite จาก
DSDropDownBase
และมีองค์ประกอบ
PopulateItemsCore เพื่อใส่ค่าใน Item
และผลตัวเลือก
BuildOutputAst

ตัวอย่าง ที่ Fix bug แล้วจาก SampleDropdownUi ของ Dynamo


using System.Collections.Generic;
using CoreNodeModels;
using Dynamo.Graph.Nodes;
using Dynamo.Utilities;
using ProtoCore.AST.AssociativeAST;
using Newtonsoft.Json;

namespace SampleLibraryUI.Examples
{
    [NodeName("Drop Down Example")]
    [NodeDescription("Fixed An example drop down node.")]
    [IsDesignScriptCompatible]
    public class DropDownExample : DSDropDownBase
    {
        public DropDownExample() : base("itemA"){
              }

        // Starting with Dynamo v2.0 you must add Json constructors for all nodeModel
        // dervived nodes to support the move from an Xml to Json file format.  Failing to
        // do so will result in incorrect ports being generated upon serialization/deserialization.
        // This constructor is called when opening a Json graph. We must also pass the deserialized 
        // ports with the json constructor and then call the base class passing the ports as parameters.
        [JsonConstructor]
        public DropDownExample(IEnumerable<PortModel> inPorts, IEnumerable<PortModel> outPorts) : base("itemA", inPorts, outPorts) { }

        protected override SelectionState PopulateItemsCore(string currentSelection)
        {
            // The Items collection contains the elements
            // that appear in the list. For this example, we
            // clear the list before adding new items, but you
            // can also use the PopulateItems method to add items
            // to the list.

            Items.Clear();

            // Create a number of DynamoDropDownItem objects 
            // to store the items that we want to appear in our list.

            var newItems = new List<DynamoDropDownItem>()
            {
                new DynamoDropDownItem("Item 0", 0),
                new DynamoDropDownItem("Item 1", 1),
                new DynamoDropDownItem("Item 2",2)
            };

            Items.AddRange(newItems);

            // Set the selected index to something other
            // than -1, the default, so that your list
            // has a pre-selection.

            SelectedIndex = 0;
            return SelectionState.Restore;
        }

        public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
        {
            // Build an AST node for the type of object contained in your Items collection.
            if (Items.Count == 0 ||  SelectedIndex <0 || SelectedIndex >= Items.Count) // Bug fixed!
            {
                return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()) };
            }

            var intNode = AstFactory.BuildIntNode((int)Items[SelectedIndex].Item);
            var assign = AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), intNode);
            return new List<AssociativeNode> { assign };

        }
    }
}

วันศุกร์ที่ 20 มีนาคม พ.ศ. 2563

สร้าง Node C# ใน Revit Dynamo โดยใช้ ZeroTouch

Dynamo เป็น การ Custom โปรแกรม Revit โดยใช้ Graphic Drag and Drop  โดยที่แต่ละ คำสั่งจะเป็น รูป Block ของคำสั่ง มีคนเขียน โปรแกรม เพื่อให้ Revit ทำงาน ได้ หลากหลาย มาก แต่บางอย่าง ก็ยุ่งยยาก เนื่องจาก ไม่ใช้ Program Language
การ เชื่อม Node ของ Dynamo จึงทำให้งานบางอย่างง่ายขึ้น เช่น การ Filter String Data  ที่ซับซ้อนโดยใช้ Rex หรือเชื่อมกับโปรแกรมระบบอื่นๆ
การ Custom Node ด้วย C# เคยเขียนใว้แล้วใน บทความ. https://thaibimpro.blogspot.com/2015/12/node-c-dynamo.html
ปัจจุบัน ง่ายกว่าเดิม โดยใข้ Tools ใน Visual Studio
วิธีการ
ให้ทำการ สร้าง New Project -> Class library ซึ่งจะเป็นชื่อใน Menu หมวด ของ Dynamo
เช่น. DynamoOk
จากนั้นไปที่ Tools->Nuget Package Manager->Browse-> พิมพ์ ZeroTouch จะเจอ
DynamoVisualProgramming.ZeroTouch
ติดตั้งลงใน Project ปัจจุบัน
แก้ Code สร้าง Class ตามต้องการ โดยกำหนด Namespace เป็น 2 ช่วงเช่น
<ชื่อหลัก>.<ชื่อหมวดงาน>
และ Method จะต่อ จาก <ชื่อหมวดงาน>


namespace PowerPartners.DynamoOk
{
    public static class FirstContact
    {
        public static string HelloWorld(string str)
        {
            string s = "Hello World " + str;
            return s;
        }
    }
}
Compile และ ใน Revit,Dyanamo ให้ กด add->import library จะได้ เมนู และ มี ชื่อตามรูป



เมื่อ Drag มา และทดลองใส่ String


แต่ เมนูนี้ จะหายไปเมื่อเข้าใหม่ ถ้าต้องการ ให้มันอยู่ ต้อง Register  UUID ของโปรแกรม และ สร้าง Json package ใว้ใน Dynamo Core

** note การ Set Debug ใน Visual Studio
Tools > Options… > Debugging > General > Check “Use Managed Compatibility Mode


วันพุธที่ 11 มีนาคม พ.ศ. 2563

Autocad load dotnet application ไม่ได้ จาก Network Drive

Window 10 มี Security เพิ่ม โดยไม่ให้ application เช่น Autocad ที่ ทำงานอยู่ netload โปรแกรมจาก Network Drive หรือ URL บางระบบ Domain จะ Load โปรแกรมไม่ได้ แม้แต่ Drive C:
วิธีแก้ ต้องไปเพิ่ม ข้อความนี้ ใน acad.exe.config ใน c:\program files\Autodesk\Autocad 20xx\

<configuration>
<runtime>
<loadFromRemoteSources enabled="true"/> </runtime>
...

วันอังคารที่ 10 มีนาคม พ.ศ. 2563

วิธี Debug C# Autocad dotnet ด้วย Visual Studio 2015-2017

การ Debug โปรแกรม C# ที่เขียนสำหรับ Autocad 2013-2x ด้วย Visual Studio 2015-19ทำได้ แต่ลึกลับ พอสมควร และมี ข้อจำกัด เนื่องจาก เขาไม่ต้องการให้ Debug ใน Process ของ Acad.exe ง่ายๆไม่ให้ Hack

วิธีการ
1. ต้องไปที่ Project ที่ ทำอยู่. Property Setting-> set เป็น Debug
2. Setting->start External program ให้เป็น c:\program files\Autodesk\Autocad xxxx\acad.exe
 Setting ->debug ไป เช็กที่ Enable Native Code Debugging
3. Tools->Options->Debugging
    เช็ก เอาออก Enable UI Debugging tools for XAML และ Edit and Continue
    เช็ก Managed Compatibility Mode

ReBuild all
และ กด F5 จะ run Autocad และ netload โปรแกรมใน ..\Debug\<program>.dll ก็จะเข้า Debug โปรแกรมที่ทำอยู่

วันอาทิตย์ที่ 3 พฤศจิกายน พ.ศ. 2562

ทำ Ribbon บน C# Form

การทำ Ribbon ใน C# Form จะใช้ ได้ ควรเป็น Dotnet 4.6.1 ในเลือกไปที่
Nuget Manager เลือก Ribbon WinForms



แต่มักจะมีปัญหาว่า Ribbon อาจจะไม่แสดง ใน Toolbox  ต้องไป set ใน Toolbox Show all

และเลือก Choose Items เลือก Ribbon ถ้าไม่เจอต้อง Browse Reference ไปที่ DLL




วางใน Form เลือก ลง Ribbon บนจอจะให้ใส่ Tab และ Panel และ ใส่ Button ได้ และกดสร้าง Event ได้ตามปรกติ


วันเสาร์ที่ 5 ตุลาคม พ.ศ. 2562

C# จัดการ Zip file

C# จัดการ Zip ให้ Reference system.io.compression และ system.io.compression.filesystem

ในการ List ไฟล์ใน Zip
   private void button_open_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();

            string zipPath = label1.Text;

                using (ZipArchive archive = ZipFile.OpenRead(zipPath))
            {
                foreach (ZipArchiveEntry entry in archive.Entries)
                {
                        // Gets the full path to ensure that relative segments are removed.
                        string destinationPath =  entry.FullName;
                        listBox1.Items.Add(destinationPath);
            
                }
            }
        }
ในการ Extract File ออกมา แล้ว edit ด้วย Notepad

  private void button_Edit_Click(object sender, EventArgs e)
        { // select file
            int index = listBox1.SelectedIndex;
            string sFile = listBox1.Items[index].ToString();
            // extract file
            string exPath = "c:/temp/";
            string zipPath = label1.Text;

            using (ZipArchive archive = ZipFile.OpenRead(zipPath))
            {
                foreach (ZipArchiveEntry entry in archive.Entries)
                {
                    // Gets the full path to ensure that relative segments are removed.
                    string destinationPath = exPath+entry.FullName;
                    if (entry.FullName == sFile)
                    { // extrac file

                        entry.ExtractToFile(destinationPath,true);
                        label_msg.Text = "Extract to " + destinationPath;
                        string editor = @"C:\WINDOWS\NOTEPAD.EXE";
                        Process.Start(editor, destinationPath);
                    }
                    
                }
            }
        }


ในการ Delete File เดิม และ จัดเก็บ


 private void button_Save_Click(object sender, EventArgs e)
        {
            int index = listBox1.SelectedIndex;
            string sFile = listBox1.Items[index].ToString();
            // extract file
            string exPath = "c:/temp/";
            string zipPath = label1.Text;

            using (ZipArchive archive = ZipFile.Open(zipPath, ZipArchiveMode.Update))
            {
                // delete old file
                foreach (ZipArchiveEntry entry in archive.Entries)
                {
                    // Gets the full path to ensure that relative segments are removed.
                    string destinationPath1 = exPath + entry.FullName;
                    if (entry.FullName == sFile)
                    { // extrac file
                        entry.Delete();
                        label_msg.Text = "delete zip " + sFile;
                        break;
                    }

                }

            }
            // update 
            using (ZipArchive archive = ZipFile.Open(zipPath, ZipArchiveMode.Update))
            { 
                string destinationPath = exPath + sFile;
                    archive.CreateEntryFromFile(destinationPath, sFile);
                    
                    label_msg.Text = "Zip to " + destinationPath;
                    return;
                
            }
        }

Revit หา Duct ตัด กำแพง

หลักการ เป็นการ หา Curve ของ Duct เป็น XYZ และ ตัดกับ Face ของ กำแพง

 public static void ductIntersectWall(ExternalCommandData cmd)
        {
            UIApplication uiapp = cmd.Application;
            UIDocument uidoc = uiapp.ActiveUIDocument;
            Autodesk.Revit.ApplicationServices.Application app = uiapp.Application;
            Autodesk.Revit.DB.Document CachedDoc = uidoc.Document;
            {
                 FilteredElementCollector WallCollector = new FilteredElementCollector(CachedDoc);
                WallCollector.OfClass(typeof(Wall));
                List<Wall> walls = WallCollector.Cast<Wall>().ToList();// หา กำแพง

                FilteredElementCollector DuctCollector = new FilteredElementCollector(CachedDoc);
                DuctCollector.OfClass(typeof(Duct)); // หา Duct

                List<Duct> ducts = DuctCollector.Cast<Duct>().ToList();
                List<XYZ> points = new List<XYZ>();

                foreach (Duct d in ducts)
                {
                    foreach (Wall w in walls)
                    {
                        LocationCurve lc = d.Location as LocationCurve;
                        Curve ductCurve = lc.Curve; // แต่ละ Duct หา เป็น เส้นCurve

                        XYZ intersection = null;

                        List<Face> wallFaces = FindWallFace(w); // หา หน้า Face ของกำแพง

                        foreach (Face f in wallFaces)
                        {
                            intersection = FindFaceCurve(ductCurve, f); // หาจุดตัด Face กับ เส้น duct
                            if (null != intersection)
                                points.Add(intersection);
                        }
                    }
                }

                StringBuilder sb = new StringBuilder();

                foreach (XYZ p in points)
                {
                    sb.AppendLine(p.ToString()); // เก็บ ไปแสดงค่าจุดตัด
                }
                TaskDialog.Show("duct inter wall(ft)", sb.ToString());
             }
            }
        // support function
        public static List<Face> FindWallFace(Wall wall)
        {
            List<Face> normalFaces = new List<Face>();

            Options opt = new Options();
            opt.ComputeReferences = true;
            opt.DetailLevel = ViewDetailLevel.Fine;

            GeometryElement e = wall.get_Geometry(opt);

            foreach (GeometryObject obj in e)
            {
                Solid solid = obj as Solid;

                if (solid != null && solid.Faces.Size > 0)
                {
                    foreach (Face face in solid.Faces)
                    {
                        PlanarFace pf = face as PlanarFace;
                        if (pf != null)
                        {
                            normalFaces.Add(pf);
                        }
                    }
                }
            }
            return normalFaces;
        }

        public static XYZ FindFaceCurve(Curve DuctCurve, Face WallFace)
        {
            //The intersection point
            IntersectionResultArray intersectionR = new IntersectionResultArray();//Intersection point set

            SetComparisonResult results;//Results of Comparison

            results = WallFace.Intersect(DuctCurve, out intersectionR);

            XYZ intersectionResult = null;//Intersection coordinate

            if (SetComparisonResult.Disjoint != results)
            {
                if (intersectionR != null)
                {
                    if (!intersectionR.IsEmpty)
                    {
                        intersectionResult = intersectionR.get_Item(0).XYZPoint;
                    }
                }
            }
            return intersectionResult;

        }

วันเสาร์ที่ 28 กันยายน พ.ศ. 2562

การอ่านเขียน ค่า Registry ด้วย Autolisp

ในการอ่านค่า Registry ด้วย Autolisp ต้องใช้ตามนี้ ใน Help ของ Autodesk ผิด

 (vl-registry-read "HKEY_CURRENT_USER\\Software\\<ชื่อกับ sub ที่ต้องการ>" "<key>")

กรณี Write
(vl-registry-write "HKEY_CURRENT_USER\\Software\\<ชื่อกับ sub ที่ต้องการ>" "<key>" "value")

วันพุธที่ 18 กันยายน พ.ศ. 2562

วิธีอ่านชื่อ Family and Type ขอ Element


  ในกรณีที่เราต้องการ ดู Family name ,Type name ของ Family จาก Element Id          


               Element e = doc.GetElement(elementId);

                Element et = doc.GetElement(e.GetTypeId()); // ไปอ่าน type 
                ElementType etype = et as ElementType;
                if (etype == null)
                    return;

              // ชื่อ type เช่น 100x100 mm.
             string typeN= etype.Name;

                FamilyInstance elFamInst = e as FamilyInstance;
                Family elFam = elFamInst.Symbol.Family;
             // ชื่อ Family เช่น Rectangular Column
            string fname =elFam.Name;
               

ค้น ทั้ง Element และ Type ใช้ c# Linq ใน Revit


Revit เก็บ Object ใน รูปแบบ element โดยมี Key เป็น ElementId การค้นมี tool ชื่อ FilteredElementCollector  
การใช้งาน ให้ใช้คู่กับ Linq 
OfClass หมายถึง type ที่ต้องการหา เช่น typeof( Family) หรือ typeof(DimensionType) เป็นต้น และ กำหนด ชื่อ จาก targetname

public static Element FindElementByName(
    Document doc,
    Type targetType,
    string targetName)
        {
            return new FilteredElementCollector(doc)
              .OfClass(targetType)
              .FirstOrDefault<Element>(
                e => e.Name.Equals(targetName));
        }

Load Family จาก File ใน Revit

การ Load Family จากไฟล์ .จะมีชื่อกับ Type ตาม file

string FamilyName = "ชื่อ Family";
string FamilyPath = "c:/temp/ชื่อ Family.rfa";


  Family family = FindElementByName( doc, typeof(Family), FamilyName) as Family;

            if (family != null) return; //already exist

            if (!File.Exists(FamilyPath))
            {
               MessageBox.Show(string.Format(
                  "Please ensure that the sample table "
                  + "family file '{0}' exists in '{1}'.",
                  FamilyName, path));

                return ;
            }

            // Load family from file:

            using (Transaction tx = new Transaction(doc))
            {
                tx.Start("Load Family");
                doc.LoadFamily(FamilyPath, out family);
                
                tx.Commit();
            }

วันอังคารที่ 17 กันยายน พ.ศ. 2562

Json ใน SQL Server 2017 และสร้าง Class ใน C#

Json ใช้ในระบบของ Javascript และ การติดต่อ ระหว่าง Cloud ระหว่างหลายภาษา เช่น python, java, dotnet. SQL Server 2017 มี Feature นี้ ด้วย

ก่อนอื่นต้อง Upgrade database ก่อน
ALTER DATABASE [TestDB] SET COMPATIBILITY_LEVEL = 130

ทดลอง Data ที่เป็น JSON

DECLARE @JSONData AS NVARCHAR(4000)
SET @JSONData = N'{
    "EmployeeInfo":{
        "FirstName":"Somchai",
        "LastName":"Saema",
        "Code":"CODED",
        "Addresses":[
            { "Address":"1234", "City":"Bangkok", "State":THAILAND"},
            { "Address":"5678", "City":"Nonthaburi", "State":"THAILAND"}
        ]
    }
}'

ตัวเช็ก ว่าเป็น Json หรือไม่
select isjson(@jsondata)
อ่านค่า
select json_value(@jsondata,'$.EmployeeInfo.Addresses[1].Address')

ดูว่าใช่หรือไม่
select isjson(@jsondata)
ดูค่า
select json_value(@jsondata,'$.EmployeeInfo.Addresses[1].Address')
select JSON_query(@jsondata,'$.EmployeeInfo.Addresses')
แก้
SET @JSONData = JSON_MODIFY(@JSONData,'$.EmployeeInfo.FirstName', 'Name'')
select json_value(@jsondata,'$.EmployeeInfo.FirstName')
เพิ่ม
SET @JSONData = JSON_MODIFY(@JSONData,'$.EmployeeInfo.MiddleName', 'NNK')
select JSON_value(@jsondata,'$.EmployeeInfo.MiddleName')

select * from openjson(@jsondata)
Select JSON_query(@jsondata,'$.EmployeeInfo.Addresses')
แก้ ค่า
SET @JSONData = JSON_MODIFY(@JSONData,'$.EmployeeInfo.FirstName', 'Rakesh')
select json_value(@jsondata,'$.EmployeeInfo.FirstName')
เพิ่ม field
SET @JSONData = JSON_MODIFY(@JSONData,'$.EmployeeInfo.MiddleName', 'MAI')
select JSON_value(@jsondata,'$.EmployeeInfo.MiddleName')

select * from openjson(@jsondata)

การ Update จะมา เป็น JSON ต้อง แตกออก โดยใช้ OPENJSON
DECLARE @v AS NVARCHAR(4000)
set @v='{"UserID":7,"UserName":"Somsak","RegDate":"2017-01-23T00:00:00"}'

ถ้า select * from OPENJSON(@v)
จะได้
 key .  value . type
UserId     7    2
UserName Somsak 1
RegDate 2017-01-23T00:00:00 1

บาง ค่า เราใช้ Where ได้เลย

select * from OPENJSON(@v) with ( UserID int '$.UserID', UserName varchar(50) '$.UserName', RegDate datetime '$.RegDate')
ผล
UserId UserName  RegDate
7 Somsak 2017-01-23 00:00:00.000


แล้วจึงใช้ Insert หรือ Update ได้ แทน @v ลงใน $$JSON$$
    string cmdtext = "INSERT INTO [temp_Users] ([UserID],[UserName],[RegDate])"+
                "Select UserID,UserName,RegDate from OPENJSON('$$JSON$$')with ( UserID int '$.UserID', UserName varchar(50) '$.UserName', RegDate datetime '$.RegDate')";

        

ในกรณีที่ได้ ผลจาก query มาแล้วต้องการเขียนเป็นโปรแกรมแบบ Class (no sql) ก็ทำได้โดยเข้า Web
json2charp.com และ เลือก Quicktype (ใน Visual Studio ต้องลง Nuget ของ Newtonsoft ก่อน)

เช่น ผลจาก Query
[{"UserID":1,"UserName":"Phar","RegDate":"2017-01-23T00:00:00"},{"UserID":2,"UserName":"Som"},{"UserID":3,"UserName":"Cho"}]



Generate จาก json2charp.com จะได้ Class .ให้ไปเปลี่ยน Welcome  Class เอา

namespace QuickType
{
    using System;
    using System.Collections.Generic;

    using System.Globalization;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;

    public partial class Welcome
    {
        [JsonProperty("UserID")]
        public long UserId { get; set; }

        [JsonProperty("UserName")]
        public string UserName { get; set; }

        [JsonProperty("RegDate", NullValueHandling = NullValueHandling.Ignore)]
        public DateTimeOffset? RegDate { get; set; }
    }

    public partial class Welcome
    {
        public static Welcome[] FromJson(string json) => JsonConvert.DeserializeObject<Welcome[]>(json, QuickType.Converter.Settings);
    }

    public static class Serialize
    {
        public static string ToJson(this Welcome[] self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
    }

    internal static class Converter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            Converters =
            {
                new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
            },
        };
    }
}

เวลาใช้ใน SQL  c# จะเป็นแบบนี้


 string connString = @"Data Source=127.0.0.1\sql_server_demo;User ID=sa;Password=???;Initial Catalog=MyDb;Integrated Security=";
           
            string cmdtext = "SELECT *  FROM [temp_Users] FOR JSON AUTO";
            using (SqlConnection conn = new SqlConnection(connString))
            {
                conn.Open();

                using (SqlCommand cmd = new SqlCommand(cmdtext, conn))
                {

                    
                   SqlDataReader rdr= cmd.ExecuteReader();

                    // Get the values
                    while (rdr.Read())
                    {
                        //listBox1.Items.Add(rdr[0]);
                        textBox1.Text =rdr[0].ToString();
                      QuickType.Welcome[] datas=  QuickType.Welcome.FromJson(textBox1.Text);
                        string username = datas[0].UserName;
                    }

                }
            }
        }

ลดเวลาในการเขียนและ Validate โปรแกรมได้มาก