Author Topic: how to move a face in a solid ?  (Read 12626 times)

0 Members and 1 Guest are viewing this topic.

ahlzl

  • Guest
Re: how to move a face in a solid ?
« Reply #15 on: June 20, 2010, 10:47:00 AM »
Wrapper to C#, Success!(CAD2008 + VS2005)

step1: Create a new ARX project

step2: Add a class: MyClass

step3: In MyClass.h, Add code:
Code: [Select]
#include "tchar.h"
step4: In MyClass.cpp, Add code:
Code: [Select]
extern "C" __declspec(dllexport) AcDb3dSolid* GetSubentIndexs()
{
AcDbObjectId entId = NULL;
AcArray<AcDbSubentId*> subIdArr;
AcEdSolidSubentitySelector subSel;
AcDb3dSolid *pSolid3d = NULL;

if (subSel.selectFaces(entId, subIdArr) == Acad::eOk)
{
acdbOpenObject(pSolid3d, entId, AcDb::kForWrite);

TCHAR subIdIndexStrs[1000];
TCHAR indexStr[10];
int index = 0;

for (int i = 0; i < subIdArr.length(); i++)
{
index = (int)(subIdArr[i]->index());
_itow(index, indexStr, 10);

if (i == 0)
{
wcscpy(subIdIndexStrs, indexStr);
}
else
{
wcscat(subIdIndexStrs, _T("-"));
wcscat(subIdIndexStrs, indexStr);
}
}

struct resbuf rb;
rb.restype = RTSTR;
rb.resval.rstring = subIdIndexStrs;
acedSetVar(_T("users1"), &rb);
return pSolid3d;
}
return NULL;
}

step5: Compile, Generate *.arx file.

step6: copy the file to AutoCAD Support Directory

strp7: Create a new C# project, Add code
Code: [Select]
using System;
using System.Runtime.InteropServices;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace Cs
{
    public class Class1
    {
        [DllImport("yourARX.arx", CallingConvention = CallingConvention.Cdecl, EntryPoint = "GetSubentIndexs")]
        public static extern IntPtr GetSubentIndexs();

        [CommandMethod("test")]
        public void MyTest()
        {
            Color myColor = Color.FromColorIndex(ColorMethod.ByLayer, 1);
 
            IntPtr rb = GetSubentIndexs();
            if (rb != IntPtr.Zero)
            {
                Solid3d solid3dEnt = DisposableWrapper.Create(typeof(Solid3d), rb, true) as Solid3d;

                if (solid3dEnt != null)
                {
                    string users1Value = (string)Application.GetSystemVariable("users1");
                    String[] strs = users1Value.Split(new char[] { '-' });
                    for (int i = 0; i < strs.Length; i++)
                    {
                        SubentityId subId = new SubentityId(SubentityType.Face, Convert.ToInt16(strs[i]));
                        solid3dEnt.SetSubentityColor(subId, myColor);
                    }
                    solid3dEnt.Close();
                }
            }
        }
    }
}

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8690
  • AKA Daniel
Re: how to move a face in a solid ?
« Reply #16 on: June 20, 2010, 07:28:47 PM »
Good start! a couple of small issues, first,  in the ARX you have a memory leak at subIdArr, you need to iterate the array and delete the pointers, Second you pass an object that's opened for write,  when you should probably pass an ObjectID  :-)

ahlzl

  • Guest
Re: how to move a face in a solid ?
« Reply #17 on: June 20, 2010, 09:20:39 PM »
Very grateful to the guidance of Daniel!

First Problem,Is this it?

Code: [Select]
static void ahlzlArxProject1_MyCommand1(void)
{
// Add your code for command ahlzlArxProject1._MyCommand1 here
AcDbObjectId entId = NULL;
AcDbEntity *pEnt;
AcDb3dSolid *pSolid3d;
AcArray<AcDbSubentId*> subIdArr;
AcEdSolidSubentitySelector subSel;

if (subSel.selectFaces(entId, subIdArr) == Acad::eOk)
{
if (acdbOpenAcDbEntity(pEnt, entId, AcDb::kForWrite) == Acad::eOk)
{
pSolid3d = (AcDb3dSolid*)pEnt;
for (int i = 0; i < subIdArr.length(); i++)
{
AcDbSubentId subId(AcDb::kFaceSubentType, subIdArr[i]->index());
pSolid3d->extrudeFaces(subIdArr, 100.0, 0.0);
[color=red]delete subIdArr[i][/color];
}
pSolid3d->close();
}
}
}

Code: [Select]
extern "C" __declspec(dllexport) AcDb3dSolid* GetSubentIndexs()
{
AcDbObjectId entId = NULL;
AcArray<AcDbSubentId*> subIdArr;
AcEdSolidSubentitySelector subSel;
AcDb3dSolid *pSolid3d = NULL;

if (subSel.selectFaces(entId, subIdArr) == Acad::eOk)
{
acdbOpenObject(pSolid3d, entId, AcDb::kForWrite);

TCHAR subIdIndexStrs[1000];
TCHAR indexStr[10];
int index = 0;

for (int i = 0; i < subIdArr.length(); i++)
{
index = (int)(subIdArr[i]->index());
_itow(index, indexStr, 10);

if (i == 0)
{
wcscpy(subIdIndexStrs, indexStr);
}
else
{
wcscat(subIdIndexStrs, _T("-"));
wcscat(subIdIndexStrs, indexStr);
}
[color=red]delete subIdArr[i];[/color]
}

struct resbuf rb;
rb.restype = RTSTR;
rb.resval.rstring = subIdIndexStrs;
acedSetVar(_T("users1"), &rb);
return pSolid3d;
}
return NULL;
}
« Last Edit: June 20, 2010, 09:23:44 PM by ahlzl »

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8690
  • AKA Daniel
Re: how to move a face in a solid ?
« Reply #18 on: June 20, 2010, 10:24:29 PM »
I might do something like this (untested) see attachment

.h
Code: [Select]
#pragma managed

#pragma once
using namespace System;
using namespace System::Text;
using namespace Autodesk::AutoCAD::DatabaseServices;
using namespace Autodesk::AutoCAD::Geometry;
using namespace Autodesk::AutoCAD::Runtime;


inline Autodesk::AutoCAD::DatabaseServices::SubentityId ToSubentityId(const AcDbSubentId& id)
{
  Autodesk::AutoCAD::DatabaseServices::SubentityId ret;
  GETSUBENTITYID(ret) = id;
  return ret;
}

namespace AcMgdWrprs
{
  public ref class Utilities
  {
     ....
    static bool SolidSubentitySelector([Out]ObjectId %solid,[Out]array<SubentityId> ^%sids);
  };
}

.cpp
Code: [Select]

#include "StdAfx.h"
#include "Utilities.h"

using namespace System;
using namespace System::Text;
using namespace System::Collections::Generic;
using namespace Autodesk::AutoCAD::DatabaseServices;
using namespace Autodesk::AutoCAD::Geometry;
using namespace Autodesk::AutoCAD::Runtime;
using namespace Autodesk::AutoCAD::EditorInput;
using namespace Autodesk::AutoCAD::ApplicationServices;

//
namespace AcMgdWrprs
{
  Utilities::Utilities(void)
  {
  }

  ...


  bool Utilities::SolidSubentitySelector( [Out]ObjectId %solid,[Out]array<SubentityId> ^%sids )
  {

    AcDbObjectId entId = NULL;
    AcDb3dSolid *pSolid3d = NULL;
    AcArray<AcDbSubentId*> subIdArr;
    AcEdSolidSubentitySelector subSel;

    if (subSel.selectFaces(entId, subIdArr) == Acad::eOk)
    {
      sids = gcnew array<SubentityId>(subIdArr.length());
      for (int i = 0; i < subIdArr.length(); i++)
      {
        AcDbSubentId *sid = subIdArr[i];
        sids[i] = ToSubentityId(*sid);
        delete sid;
      }
      solid = ToObjectId(entId);
      return true;
    }
    return false;
  }
}

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8690
  • AKA Daniel
Re: how to move a face in a solid ?
« Reply #19 on: June 20, 2010, 10:33:34 PM »

C#
Code: [Select]
namespace ExecMethod
{
  public class Commands
  {
    //++--
    [CommandMethod("doit")]
    static public void test()
    {
      Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;

      SubentityId[] sids;
      ObjectId id;
      if(AcMgdWrprs.Utilities.SolidSubentitySelector(out id, out sids))
      {
        ed.WriteMessage("\n{0}", id);

        foreach (SubentityId sid in sids)
          ed.WriteMessage("\n{0}", sid.Index);
     
      }
    }
  }
}

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8690
  • AKA Daniel
Re: how to move a face in a solid ?
« Reply #20 on: June 20, 2010, 10:55:56 PM »
here is extrudeFaces

Code: [Select]
bool Utilities::SolidExtrudeFaces( double width, double taper )
  {
    AcDbObjectId entId = NULL;
    AcDb3dSolid *pSolid3d = NULL;
    AcArray<AcDbSubentId*> subIdArr;
    AcEdSolidSubentitySelector subSel;

    if (subSel.selectFaces(entId, subIdArr) == Acad::eOk)
    {
      AcDbObjectPointer<AcDb3dSolid> spr(entId,AcDb::kForWrite);
      spr->extrudeFaces(subIdArr,width,taper);
      for (int i = 0; i < subIdArr.length(); i++)
      {
        AcDbSubentId *sid = subIdArr[i];
        delete sid;
      }
      return true;
    }
    return false;
  }

Code: [Select]
   [CommandMethod("doit")]
    static public void test()
    {
      Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
      if (AcMgdWrprs.Utilities.SolidExtrudeFaces(10, 0))
      {
       
      }
    }


It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8690
  • AKA Daniel
Re: how to move a face in a solid ?
« Reply #21 on: June 20, 2010, 10:57:32 PM »
doh, I see that was already in the API  :laugh:

ahlzl

  • Guest
Re: how to move a face in a solid ?
« Reply #22 on: June 20, 2010, 11:11:54 PM »
Daniel is too great!

I would like to come to Shanghai (I was born in Shanghai),When to ask for Danie ARX,But I do not speak English! :oops: :oops: :oops:

SEANT

  • Bull Frog
  • Posts: 345
Re: how to move a face in a solid ?
« Reply #23 on: June 21, 2010, 04:11:16 AM »
Thanks for the effort guys.  When I do make the jump, the study material here - and the other forum sections - will undoubtedly make the water more inviting. :-)



doh, I see that was already in the API  :laugh:

It is in the .NET API,  but the method appeared to be setup incorrectly (AutoCAD 2009).  I'll look through these later posts for clues to a straight .NET solution.  I certainly wouldn't be surprised if I missed something on my first go.
Sean Tessier
AutoCAD 2016 Mechanical