<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3062125617693317780</id><updated>2012-02-16T11:19:39.476+01:00</updated><category term='named pipes map3d'/><category term='sdo_geomerty'/><category term='IPC Map3d communication namedpipes'/><category term='Topology Framework .NET (TF.NET)'/><title type='text'>Topology Framework</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Maksim Sestic</name><uri>http://www.blogger.com/profile/11155932635442483931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>21</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-1307095794251601620</id><published>2010-02-03T14:46:00.004+01:00</published><updated>2010-02-03T15:01:30.967+01:00</updated><title type='text'>Autodesk Map3d 2010 with WCF (III)</title><content type='html'>&lt;div&gt;Author: Jonio, Dennis&lt;/div&gt;&lt;br /&gt;The snippets below are an example for a client. It did take some time to research the parameters required for a long lived(8 hour) service. It turned out to be that two(2) parameters have to be set, InactivityTimeout and ReceiveTimeout.  Needless to say these should match the service’s ServiceEndpoint configuration.&lt;br /&gt;&lt;br /&gt;In general the way the service works is that you can send it data with any one(1) of three(3) different methods. I only employ one(1) of those methods in this case. If your application has “Subscribed” you will be sent via the callback method any and all output from the service. I really do not attempt to track the “state” of anything. As the book explains, and to say the least, state tracking is probably not the best way to expend your time and energy. &lt;br /&gt;&lt;br /&gt;From Map3d's perspective the new, improved DataBridge is really a non issue. For all intent and purpose Map3d will see things the same way. I am sure that as time moves on the complexity of "if" and "case" statements will grow.&lt;br /&gt;I plan on following this article with the complete DataBridge Version II.&lt;br /&gt;Source code snippets for a client(C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;&lt;br /&gt;     public static IByteSrvcWCallback SrvcHost;&lt;br /&gt;     public static ByteSrvcCallbackImpl callbackImpl;&lt;br /&gt;     public static DuplexChannelFactory&lt;IByteSrvcWCallback&gt; dcf;&lt;br /&gt;     public static Guid MyServicedName;&lt;br /&gt;     public static string MyPrefixForMap3dDQ = "MDADCLSSFYIO";&lt;br /&gt;     public static string AddressOfReliableSessionService = "net.tcp://localhost:9080/DataService";&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;     public MainForm()&lt;br /&gt;     {&lt;br /&gt;         InitializeComponent();&lt;br /&gt;         NetTcpBinding ntb = new NetTcpBinding(SecurityMode.None, true);&lt;br /&gt;         ntb.ReliableSession.Enabled = true;&lt;br /&gt;         ntb.ReliableSession.Ordered = true;&lt;br /&gt;         ntb.ReliableSession.InactivityTimeout = new TimeSpan(0, 8, 0, 0);&lt;br /&gt;         ntb.ReceiveTimeout = new TimeSpan(0, 8, 0, 0);&lt;br /&gt;         callbackImpl = new ByteSrvcCallbackImpl();&lt;br /&gt;         InstanceContext ic = new InstanceContext(callbackImpl);&lt;br /&gt;         dcf = new DuplexChannelFactory&lt;IByteSrvcWCallback&gt;(&lt;br /&gt;                      ic,&lt;br /&gt;                      ntb,&lt;br /&gt;                      new EndpointAddress(AddressOfReliableSessionService));&lt;br /&gt;         SrvcHost = dcf.CreateChannel();&lt;br /&gt;         callbackImpl.OnGotControlPacket += &lt;br /&gt;new ByteSrvcCallbackImpl.GotControlPacket(WCF_RcvdSrvcControlPacket);&lt;br /&gt;         MyServicedName = Guid.Empty;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;        void WCF_RcvdSrvcControlPacket(byte[] ba)&lt;br /&gt;        {&lt;br /&gt;            byte[] x = callbackImpl.ControlPacket;&lt;br /&gt;            //&lt;br /&gt;            //Here is the callback&lt;br /&gt;            //Do something useful with the data that the Service has sent to you&lt;br /&gt;           //&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public int WCF_SendToMap3dDataBridge(byte[] ba)&lt;br /&gt;        {&lt;br /&gt;            return SrvcHost.DQPipedIn(MyPrefixForMap3dDQ, ba);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void btnSUBSCRIBE_Click(object sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                if (MyServicedName == Guid.Empty)&lt;br /&gt;                    MyServicedName = SrvcHost.Subscribe();&lt;br /&gt;            }&lt;br /&gt;            catch (EndpointNotFoundException _epnfX)&lt;br /&gt;            {&lt;br /&gt;                AppendMessage("EndPoint ERROR: " + _epnfX.Message);&lt;br /&gt;            }&lt;br /&gt;            catch (System.Exception _eX)&lt;br /&gt;            {&lt;br /&gt;                AppendMessage("ERROR: " + _eX.Message);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void btnUNSUBSCRIBE_Click(object sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                if (MyServicedName != Guid.Empty)&lt;br /&gt;                    SrvcHost.UnSubscribe(MyServicedName);&lt;br /&gt;                MyServicedName = Guid.Empty;&lt;br /&gt;            }&lt;br /&gt;            catch (EndpointNotFoundException _epnfX)&lt;br /&gt;            {&lt;br /&gt;                AppendMessage("EndPoint ERROR: " + _epnfX.Message);&lt;br /&gt;            }&lt;br /&gt;            catch (System.Exception _eX)&lt;br /&gt;            {&lt;br /&gt;                AppendMessage("ERROR: " + _eX.Message);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-1307095794251601620?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/1307095794251601620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2010/02/autodesk-map3d-2010-with-wcf-iii.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/1307095794251601620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/1307095794251601620'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2010/02/autodesk-map3d-2010-with-wcf-iii.html' title='Autodesk Map3d 2010 with WCF (III)'/><author><name>Dennis Jonio</name><uri>http://www.blogger.com/profile/14478827118325682041</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-5547906768620195680</id><published>2010-02-01T20:38:00.008+01:00</published><updated>2010-02-01T21:05:42.250+01:00</updated><title type='text'>Autodesk Map3d 2010 with WCF (II)</title><content type='html'>&lt;div&gt;Author: Jonio, Dennis&lt;/div&gt;&lt;br /&gt;I make absolutely no attempt here to explain why I have done the things the way I have done them in relationship to the grand scheme of WCF. There is just too much to explain and you really should get the book and improve on what I have done. I stopped a long time ago in trying to force Map3d to do multi-threading. As it turns out this is not debilitating at all, just use a Form.&lt;br /&gt;The following are my concrete classes for the WCF interfaces found in the previous article. Making no value judgments, you do have to be impressed with how much Microsoft has done in producing the “behind the scenes” transport functionality. Since I wanted “required, reliable sessions with binary transport” I have coded towards the NetTcpBinding and the NetNamedPipeBinding.&lt;br /&gt;As you can see there are two(2) methods for getting data to the service and the service has one(1) method to send data back to the client. During research I happened upon this multiple client subscription concept with a simple Guid identifier. I desperately wanted some kind of "session identifier" that was all ready in place, generic and robust. If you do the reading you will discover WCF has the concept of SessionId but in my mind's eye it is too crippled to be of any use for my purpose. This subscription paradigm struck me as a good, simple and straightforward idea.&lt;br /&gt;The service itself.&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Linq;&lt;br /&gt;using System.Text;&lt;br /&gt;using System.ServiceModel;&lt;br /&gt;&lt;br /&gt;namespace DplXByteSrvcs&lt;br /&gt;{&lt;br /&gt;    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,&lt;br /&gt;                     ConcurrencyMode = ConcurrencyMode.Reentrant)]&lt;br /&gt;    public class ByteSrvcWCallbackImpl : IByteSrvcWCallback&lt;br /&gt;    {&lt;br /&gt;        public delegate void DataIsReady(byte[] hotData);&lt;br /&gt;        public DataIsReady DataReady = null;&lt;br /&gt;&lt;br /&gt;        public delegate void DQDataIsReady(string destinationQ, byte[] hotData);&lt;br /&gt;        public DQDataIsReady DQDataReady = null;&lt;br /&gt;&lt;br /&gt;        public delegate void GotControlPacket(byte[] hotPacket);&lt;br /&gt;        public GotControlPacket OnGotControlPacket = null;&lt;br /&gt;&lt;br /&gt;        public readonly Dictionary&lt;Guid, IByteSrvcCallback&gt; SrvcClients = &lt;br /&gt;                                                new Dictionary&lt;Guid, IByteSrvcCallback&gt;();&lt;br /&gt;&lt;br /&gt;        public void ControlPacket(byte[] ba)&lt;br /&gt;        {&lt;br /&gt;            int rtnval = 0;&lt;br /&gt;            if (ba != null)&lt;br /&gt;                rtnval = ba.Length;&lt;br /&gt;            if (OnGotControlPacket != null)&lt;br /&gt;                OnGotControlPacket(ba);&lt;br /&gt;&lt;br /&gt;            IByteSrvcCallback callback = OperationContext.Current.GetCallbackChannel&lt;IByteSrvcCallback&gt;();&lt;br /&gt;            if (!SrvcClients.ContainsValue(callback))&lt;br /&gt;            {&lt;br /&gt;                Guid clientId = Guid.NewGuid();&lt;br /&gt;                if (callback != null)&lt;br /&gt;                {&lt;br /&gt;                    lock (SrvcClients)&lt;br /&gt;                    {&lt;br /&gt;                        SrvcClients.Add(clientId, callback);&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        public int PipedIn(byte[] data)&lt;br /&gt;        {&lt;br /&gt;            int rtnval = 0;&lt;br /&gt;            if (data != null)&lt;br /&gt;                rtnval = data.Length;&lt;br /&gt;&lt;br /&gt;            if (DataReady != null)&lt;br /&gt;                DataReady(data);&lt;br /&gt;&lt;br /&gt;            return rtnval;&lt;br /&gt;        }&lt;br /&gt;        public int DQPipedIn(string destinationQ, byte[] data)&lt;br /&gt;        {&lt;br /&gt;            int rtnval = 0;&lt;br /&gt;            if (data != null)&lt;br /&gt;                rtnval = data.Length;&lt;br /&gt;&lt;br /&gt;            if (DQDataReady != null)&lt;br /&gt;                DQDataReady(destinationQ, data);&lt;br /&gt;&lt;br /&gt;            return rtnval;&lt;br /&gt;        }&lt;br /&gt;        Guid IByteSrvcWCallback.Subscribe()&lt;br /&gt;        {&lt;br /&gt;            IByteSrvcCallback callback =&lt;br /&gt;                OperationContext.Current.GetCallbackChannel&lt;IByteSrvcCallback&gt;();&lt;br /&gt;            Guid clientId = Guid.NewGuid();&lt;br /&gt;            if (callback != null)&lt;br /&gt;            {&lt;br /&gt;                lock (SrvcClients)&lt;br /&gt;                {&lt;br /&gt;                    SrvcClients.Add(clientId, callback);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            return clientId;&lt;br /&gt;        }&lt;br /&gt;        void IByteSrvcWCallback.UnSubscribe(Guid clientGID)&lt;br /&gt;        {&lt;br /&gt;            lock (SrvcClients)&lt;br /&gt;            {&lt;br /&gt;                if (SrvcClients.ContainsKey(clientGID))&lt;br /&gt;                {&lt;br /&gt;                    SrvcClients.Remove(clientGID);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        void IByteSrvcWCallback.NoOpButKeepAlive() { }&lt;br /&gt;&lt;br /&gt;    }//EOC&lt;br /&gt;}//EONS&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You will discover as I did that the communications piece is really all about the client. Nothing much happens without them. &lt;br /&gt;Now for the Client the callback class.&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Linq;&lt;br /&gt;using System.Text;&lt;br /&gt;&lt;br /&gt;namespace DplXByteSrvcs&lt;br /&gt;{&lt;br /&gt;    public class ByteSrvcCallbackImpl : IByteSrvcCallback&lt;br /&gt;    {&lt;br /&gt;        public delegate void GotControlPacket(byte[] hotPacket);&lt;br /&gt;        public GotControlPacket OnGotControlPacket = null;&lt;br /&gt;&lt;br /&gt;        private byte[] m_ba;&lt;br /&gt;        public byte[] ControlPacket&lt;br /&gt;        {&lt;br /&gt;            get { return m_ba; }&lt;br /&gt;        }&lt;br /&gt;        public void SentControlPacket(byte[] ba)&lt;br /&gt;        {&lt;br /&gt;            m_ba = ba;&lt;br /&gt;            if (OnGotControlPacket != null)&lt;br /&gt;                OnGotControlPacket(ba);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-5547906768620195680?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/5547906768620195680/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2010/02/wcf-with-map3d-ii.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/5547906768620195680'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/5547906768620195680'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2010/02/wcf-with-map3d-ii.html' title='Autodesk Map3d 2010 with WCF (II)'/><author><name>Dennis Jonio</name><uri>http://www.blogger.com/profile/14478827118325682041</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-6520335127247675092</id><published>2010-02-01T15:18:00.010+01:00</published><updated>2010-02-01T20:46:03.401+01:00</updated><title type='text'>Autodesk Map3d 2010 and WCF (I)</title><content type='html'>&lt;div&gt;Author: Jonio, Dennis&lt;/div&gt;&lt;br /&gt;Well, I finally finished my first Windows Communication Foundation(WCF) project. Ever since .NET Framework 3.0 came out I had been curious but until now the chance to delve into it just never appeared.  The prompt was to get some flexibility into the IPC chores between my custom Autodesk application modules(netloads) and my .NET applications. &lt;br /&gt;First off, I certainly join the chorus that promotes getting &lt;b&gt;Juval Lowy’s&lt;/b&gt; work &lt;b&gt;&lt;u&gt;Programming WCF Services&lt;/b&gt;&lt;/u&gt; (in my case 2nd Edition). There is a multitude of nuance and subtlety that would be left to chance without reading this work. In addition I do not have a clue where else a person would go to get his kind of depth of understanding. A real "must have" if you are serious about WCF. &lt;br /&gt;As I spent more time with WCF I certainly learned of some of its strengths and weakness’. I really did waiver a lot concerning implementing the callback interface versus just using the simplest of operation contracts with each executable acting as a hosting service and likewise a client. This would have made this new interface very similar to my previous NamedPipe interface in that both sides act as host and client. In the end I choose the WCF DuplexChannel/callback paradigm because I figured out the rather straightforward way to keep the session(s) alive over an extended period of time. &lt;br /&gt;If you are at all familiar with my previous work with IPC you know that I pass serialized datasets around as opposed to passing more granular objects.  I do not stray from this paradigm. It has served me well and I cannot think of any reason to change. &lt;br /&gt;&lt;br /&gt;The following are my interface definitions for the service and callback. I will leave the class implementation for a follow up.&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Linq;&lt;br /&gt;using System.Text;&lt;br /&gt;using System.ServiceModel;&lt;br /&gt;&lt;br /&gt;namespace DplXByteSrvcs&lt;br /&gt;{&lt;br /&gt;    [ServiceContract(Namespace = "WCF.MDAD.SERVICES",&lt;br /&gt;                    CallbackContract = typeof(IByteSrvcCallback),&lt;br /&gt;                    SessionMode = SessionMode.Required)]&lt;br /&gt;    public interface IByteSrvcWCallback&lt;br /&gt;    {&lt;br /&gt;        [OperationContract(IsOneWay = true)]&lt;br /&gt;        void ControlPacket(byte[] baIn);&lt;br /&gt;&lt;br /&gt;        [OperationContract]&lt;br /&gt;        [TransactionFlow(TransactionFlowOption.Allowed)]&lt;br /&gt;        int PipedIn(byte[] data);&lt;br /&gt;&lt;br /&gt;        [OperationContract]&lt;br /&gt;        [TransactionFlow(TransactionFlowOption.Allowed)]&lt;br /&gt;        int DQPipedIn(string destinationQ, byte[] data);&lt;br /&gt;&lt;br /&gt;        [OperationContract]&lt;br /&gt;        Guid Subscribe();&lt;br /&gt;        [OperationContract(IsOneWay = true)]&lt;br /&gt;        void UnSubscribe(Guid clientId);&lt;br /&gt;        [OperationContract(IsOneWay = true)]&lt;br /&gt;        void NoOpButKeepAlive();&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;    public interface IByteSrvcCallback&lt;br /&gt;    {&lt;br /&gt;        [OperationContract(IsOneWay = true)]&lt;br /&gt;        void SentControlPacket(byte[] baOut);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-6520335127247675092?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/6520335127247675092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2010/02/autodesk-map3d-2010-and-wcf.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/6520335127247675092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/6520335127247675092'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2010/02/autodesk-map3d-2010-and-wcf.html' title='Autodesk Map3d 2010 and WCF (I)'/><author><name>Dennis Jonio</name><uri>http://www.blogger.com/profile/14478827118325682041</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-5721137491880522431</id><published>2009-11-19T17:10:00.004+01:00</published><updated>2009-12-03T11:03:44.774+01:00</updated><title type='text'>(VII) New SDO_GEOMETRY &lt;-&gt; Autodesk Map3d 2010</title><content type='html'>&lt;div&gt;Author: Jonio, Dennis&lt;/div&gt;&lt;br /&gt;The next and last items on the list ...&lt;br /&gt;&lt;li&gt;Given one or more Autodesk/Map3d objects decompose it(them) into “Drawable(s)”.&lt;br /&gt;&lt;li&gt;Given a “DrawAble” compose a Autodesk/Map3d object.&lt;br /&gt;&lt;br /&gt;This is the class that interacts with Autodesk Map3d. (I have removed a few things that are not importtant to the discussion here.) &lt;br /&gt;First, as time has gone on I have grown weary of parseing out Autodesk/Map3d objects and manipulating them. I gravitated toward AppendLoopFromBoundary() and BalanceTree() for MPolygon construction. Just a lot less code on my part. If it isn't a Point type I force just about everything to a Polyline at one time or the other. If you really need true 3D objects you shouldn't be reading this anyway.&lt;br /&gt;Just some things of note:&lt;br /&gt;&lt;li&gt; I never output an Oracle Circle&lt;br /&gt;&lt;li&gt; I never output an Oracle Rectangle&lt;br /&gt;&lt;li&gt; I never output an Oracle SDO_POINT&lt;br /&gt;I will read them and write them as Autdesk objects but after this they loose their identity as such. &lt;br /&gt;&lt;br /&gt;This is the last post on this topic. I have decided NOT to post the working source and project. If you are interested in the final work leave a comment with your email address. &lt;br /&gt;&lt;br /&gt;Since I produce only VALIDATED geometry I will be working on the post of my latest iteration of my IO class for doing validation against the database. &lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;using MDADDrawAbles;&lt;br /&gt;using SDO = MDADDrawAbles.DrawAbleSdoGeometryUtil;&lt;br /&gt;&lt;br /&gt;using NetSdoGeometry;&lt;br /&gt;&lt;br /&gt;namespace MDADDrawAbleDwg&lt;br /&gt;{&lt;br /&gt;    public class DrawAbleDwg&lt;br /&gt;    {&lt;br /&gt;        //&lt;br /&gt;        // POINT&lt;br /&gt;        //&lt;br /&gt;        public static DrawAble PointDrawAbleFromPoint(Point3d p3d, int _dimensionality)&lt;br /&gt;        {&lt;br /&gt;            DrawAble dp = new DrawAble(DrawAbleType.Point, _dimensionality);&lt;br /&gt;            DrawAbleSubComponent dpc = new DrawAbleSubComponent();&lt;br /&gt;            dpc.Etype = DrawAbleSubComponentEType.Point;&lt;br /&gt;            int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;&lt;br /&gt;            dpc.Ords = new decimal[len];&lt;br /&gt;            dpc.Ords[0] = System.Convert.ToDecimal(p3d.X);&lt;br /&gt;            dpc.Ords[1] = System.Convert.ToDecimal(p3d.Y);&lt;br /&gt;            if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                dpc.Ords[2] = System.Convert.ToDecimal(p3d.Z);&lt;br /&gt;            dp.SubComponents.Add(dpc);&lt;br /&gt;            return dp;&lt;br /&gt;        }&lt;br /&gt;        public static DrawAble PointDrawAbleFromPoint(DBPoint dbp, int _dimensionality)&lt;br /&gt;        {&lt;br /&gt;            DrawAble dp = new DrawAble(DrawAbleType.Point, _dimensionality);&lt;br /&gt;            DrawAbleSubComponent dpc = new DrawAbleSubComponent();&lt;br /&gt;            dpc.Etype = DrawAbleSubComponentEType.Point;&lt;br /&gt;            int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;&lt;br /&gt;            dpc.Ords = new decimal[len];&lt;br /&gt;            dpc.Ords[0] = System.Convert.ToDecimal(dbp.Position.X);&lt;br /&gt;            dpc.Ords[1] = System.Convert.ToDecimal(dbp.Position.Y);&lt;br /&gt;            if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                dpc.Ords[2] = System.Convert.ToDecimal(dbp.Position.Z);&lt;br /&gt;            dp.SubComponents.Add(dpc);&lt;br /&gt;            return dp;&lt;br /&gt;        }&lt;br /&gt;        //&lt;br /&gt;        // POINT CLUSTER&lt;br /&gt;        //&lt;br /&gt;        public static DrawAble PointClusterDrawAbleFromPointList(List&lt;Point3d&gt; p3dList, int _dimensionality)&lt;br /&gt;        {&lt;br /&gt;            DrawAble dp = new DrawAble(DrawAbleType.Point, _dimensionality);&lt;br /&gt;            DrawAbleSubComponent dpc = new DrawAbleSubComponent();&lt;br /&gt;            dpc.Etype = DrawAbleSubComponentEType.PointCluster;&lt;br /&gt;            int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;&lt;br /&gt;            dpc.Ords = new decimal[len * p3dList.Count];&lt;br /&gt;            int p3d_counter = 0;&lt;br /&gt;            for (int _k = 0; _k &lt; dpc.Ords.Length; )&lt;br /&gt;            {&lt;br /&gt;                dpc.Ords[_k] = System.Convert.ToDecimal(p3dList[p3d_counter].X);&lt;br /&gt;                dpc.Ords[_k + 1] = System.Convert.ToDecimal(p3dList[p3d_counter].Y);&lt;br /&gt;                if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                    dpc.Ords[_k + 2] = System.Convert.ToDecimal(p3dList[p3d_counter].Z);&lt;br /&gt;                _k = _k + len;&lt;br /&gt;                p3d_counter = p3d_counter + 1;&lt;br /&gt;            }&lt;br /&gt;            dpc.Elem = new int[] { 0, 1, p3dList.Count };&lt;br /&gt;            dp.SubComponents.Add(dpc);&lt;br /&gt;            return dp;&lt;br /&gt;        }&lt;br /&gt;        //&lt;br /&gt;        // LINES&lt;br /&gt;        //&lt;br /&gt;        public static DrawAble LineCurveDrawAbleFromPolyline(Polyline pl, Polyline2d pl2d, Polyline3d pl3d, int _dimensionality)&lt;br /&gt;        {&lt;br /&gt;            DrawAble dl = new DrawAble(DrawAbleType.Line, _dimensionality);&lt;br /&gt;            int hasBulgesCount = 0;&lt;br /&gt;            Point3dCollection tmppts = null;&lt;br /&gt;            DoubleCollection tmpblgs = null;&lt;br /&gt;            Point3d[] pts = null;&lt;br /&gt;            double[] blgs = null;&lt;br /&gt;            if (pl != null)&lt;br /&gt;            {&lt;br /&gt;                tmppts = new Point3dCollection();&lt;br /&gt;                tmpblgs = new DoubleCollection();&lt;br /&gt;                int i = 0;&lt;br /&gt;                for (; i &lt; pl.NumberOfVertices; i++)&lt;br /&gt;                {&lt;br /&gt;                    switch (pl.GetSegmentType(i))&lt;br /&gt;                    {&lt;br /&gt;                        case SegmentType.Arc:&lt;br /&gt;                            CircularArc2d ca2d = pl.GetArcSegment2dAt(i);&lt;br /&gt;                            double bulge = GetBulge2d(ca2d);&lt;br /&gt;                            tmpblgs.Add(bulge);&lt;br /&gt;                            tmppts.Add(new Point3d(ca2d.StartPoint.X, ca2d.StartPoint.Y, pl.GetPoint3dAt(i).Z));&lt;br /&gt;                            hasBulgesCount++;&lt;br /&gt;                            ca2d.Dispose();&lt;br /&gt;                            break;&lt;br /&gt;                        default:&lt;br /&gt;                            tmpblgs.Add(0.0);&lt;br /&gt;                            tmppts.Add(new Point3d(pl.GetPoint3dAt(i).X, pl.GetPoint3dAt(i).Y, pl.GetPoint3dAt(i).Z));&lt;br /&gt;                            break;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                // Do NOT duplicate any point ... this appears to have different behavior for &lt;br /&gt;                // the 2D and 3D polylines so we will check them all.&lt;br /&gt;                if (pl.Closed &amp;&amp; (tmppts[0].IsEqualTo(tmppts[tmppts.Count - 1]) == false))&lt;br /&gt;                {&lt;br /&gt;                    //tmppts.Add(new Point3d(pl.GetPoint2dAt(0).X, pl.GetPoint2dAt(0).Y, 0.0));&lt;br /&gt;                    tmppts.Add(new Point3d(pl.GetPoint3dAt(0).X, pl.GetPoint3dAt(0).Y, pl.GetPoint3dAt(0).Z));&lt;br /&gt;                    tmpblgs.Add(0.0);&lt;br /&gt;                }&lt;br /&gt;                // Now we can dimensions our array stuctures and fill them up&lt;br /&gt;                pts = new Point3d[tmppts.Count];&lt;br /&gt;                blgs = new double[tmppts.Count];&lt;br /&gt;                for (int z = 0; z &lt; tmppts.Count; z++)&lt;br /&gt;                {&lt;br /&gt;                    pts[z] = new Point3d(tmppts[z].X, tmppts[z].Y, tmppts[z].Z);&lt;br /&gt;                    blgs[z] = tmpblgs[z];&lt;br /&gt;                }&lt;br /&gt;                tmppts.Clear();&lt;br /&gt;                tmppts.Dispose();&lt;br /&gt;                tmpblgs.Clear();&lt;br /&gt;            }&lt;br /&gt;            //END OF POLYLINE&lt;br /&gt;            //START OF POLYLINE2D&lt;br /&gt;            if (pl2d != null)&lt;br /&gt;            {&lt;br /&gt;                // No way of knowing how many we have so we need this to collect the points&lt;br /&gt;                tmppts = new Point3dCollection();&lt;br /&gt;                tmpblgs = new DoubleCollection();&lt;br /&gt;                if (pl2d.PolyType == Poly2dType.SimplePoly)&lt;br /&gt;                {&lt;br /&gt;                    Transaction t = pl2d.Database.TransactionManager.StartTransaction();&lt;br /&gt;                    IEnumerator iterate = pl2d.GetEnumerator();&lt;br /&gt;                    while (iterate.MoveNext())&lt;br /&gt;                    {&lt;br /&gt;                        ObjectId id = (ObjectId)iterate.Current;&lt;br /&gt;                        Vertex2d vertex = (Vertex2d)t.GetObject(id, OpenMode.ForRead);&lt;br /&gt;                        tmppts.Add(vertex.Position);&lt;br /&gt;                        tmpblgs.Add(vertex.Bulge);&lt;br /&gt;                        if (vertex.Bulge != 0.0)&lt;br /&gt;                            hasBulgesCount++;&lt;br /&gt;                    }&lt;br /&gt;                    t.Abort();&lt;br /&gt;                    t.Dispose();&lt;br /&gt;                }&lt;br /&gt;                else&lt;br /&gt;                {&lt;br /&gt;                    DBObjectCollection collection = new DBObjectCollection();&lt;br /&gt;                    pl2d.Explode(collection);&lt;br /&gt;                    foreach (Line line in collection)&lt;br /&gt;                    {&lt;br /&gt;                        tmppts.Add(line.StartPoint);&lt;br /&gt;                        tmpblgs.Add(0.0);&lt;br /&gt;                        tmppts.Add(line.EndPoint);&lt;br /&gt;                        tmpblgs.Add(0.0);&lt;br /&gt;                    }&lt;br /&gt;                    collection.Dispose();&lt;br /&gt;                }&lt;br /&gt;                // Do NOT duplicate any point&lt;br /&gt;                if (pl2d.Closed &amp;&amp; (tmppts[0].IsEqualTo(tmppts[tmppts.Count - 1]) == false))&lt;br /&gt;                {&lt;br /&gt;                    tmppts.Add(tmppts[0]);&lt;br /&gt;                    tmpblgs.Add(0.0);&lt;br /&gt;                }&lt;br /&gt;                // Now we can dimensions our array stuctures and fill them up&lt;br /&gt;                pts = new Point3d[tmppts.Count];&lt;br /&gt;                blgs = new double[tmppts.Count];&lt;br /&gt;                for (int z = 0; z &lt; tmppts.Count; z++)&lt;br /&gt;                {&lt;br /&gt;                    pts[z] = new Point3d(tmppts[z].X, tmppts[z].Y, tmppts[z].Z);&lt;br /&gt;                    blgs[z] = tmpblgs[z];&lt;br /&gt;                }&lt;br /&gt;                tmppts.Clear();&lt;br /&gt;                tmppts.Dispose();&lt;br /&gt;                tmpblgs.Clear();&lt;br /&gt;            }&lt;br /&gt;            //END OF POLYLINE2D&lt;br /&gt;            //START OF POLYLINE3D&lt;br /&gt;            if (pl3d != null)&lt;br /&gt;            {&lt;br /&gt;                tmppts = new Point3dCollection();&lt;br /&gt;                tmpblgs = new DoubleCollection();&lt;br /&gt;                if (pl3d.PolyType == Poly3dType.SimplePoly)&lt;br /&gt;                {&lt;br /&gt;                    Transaction t = pl3d.Database.TransactionManager.StartTransaction();&lt;br /&gt;                    IEnumerator iterator = pl3d.GetEnumerator();&lt;br /&gt;                    while (iterator.MoveNext())&lt;br /&gt;                    {&lt;br /&gt;                        ObjectId id = (ObjectId)iterator.Current;&lt;br /&gt;                        PolylineVertex3d vertex3d = (PolylineVertex3d)t.GetObject(id, OpenMode.ForRead);&lt;br /&gt;                        tmppts.Add(vertex3d.Position);&lt;br /&gt;                        tmpblgs.Add(0.0);&lt;br /&gt;                    }&lt;br /&gt;                    t.Abort();&lt;br /&gt;                    t.Dispose();&lt;br /&gt;                }&lt;br /&gt;                else&lt;br /&gt;                {&lt;br /&gt;                    DBObjectCollection collection = new DBObjectCollection();&lt;br /&gt;                    pl3d.Explode(collection);&lt;br /&gt;                    foreach (Line line in collection)&lt;br /&gt;                    {&lt;br /&gt;                        tmppts.Add(line.StartPoint);&lt;br /&gt;                        tmpblgs.Add(0.0);&lt;br /&gt;                        tmppts.Add(line.EndPoint);&lt;br /&gt;                        tmpblgs.Add(0.0);&lt;br /&gt;                    }&lt;br /&gt;                    collection.Dispose();&lt;br /&gt;                }&lt;br /&gt;                // Do NOT duplicate any point&lt;br /&gt;                if (pl3d.Closed &amp;&amp; (tmppts[0].IsEqualTo(tmppts[tmppts.Count - 1]) == false))&lt;br /&gt;                {&lt;br /&gt;                    tmppts.Add(tmppts[0]);&lt;br /&gt;                    tmpblgs.Add(0.0);&lt;br /&gt;                }&lt;br /&gt;                // Now we can dimensions our array stuctures and fill them up&lt;br /&gt;                pts = new Point3d[tmppts.Count];&lt;br /&gt;                blgs = new double[tmppts.Count];&lt;br /&gt;                for (int z = 0; z &lt; tmppts.Count; z++)&lt;br /&gt;                {&lt;br /&gt;                    pts[z] = new Point3d(tmppts[z].X, tmppts[z].Y, tmppts[z].Z);&lt;br /&gt;                    blgs[z] = tmpblgs[z];&lt;br /&gt;                }&lt;br /&gt;                tmppts.Clear();&lt;br /&gt;                tmppts.Dispose();&lt;br /&gt;                tmpblgs.Clear();&lt;br /&gt;            }&lt;br /&gt;            //END OF POLYLINE3D&lt;br /&gt;            //&lt;br /&gt;            // Finished getting all the ordinates and bulges for this linecurve&lt;br /&gt;            //&lt;br /&gt;            DrawAbleSubComponent dlc = new DrawAbleSubComponent();&lt;br /&gt;            if (hasBulgesCount == 0)&lt;br /&gt;            {&lt;br /&gt;                dlc.Etype = DrawAbleSubComponentEType.SimpleLine;&lt;br /&gt;                int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;&lt;br /&gt;                dlc.Ords = new decimal[len * pts.Length];&lt;br /&gt;                int pts_counter = 0;&lt;br /&gt;                for (int _k = 0; _k &lt; dlc.Ords.Length; )&lt;br /&gt;                {&lt;br /&gt;                    dlc.Ords[_k] = System.Convert.ToDecimal(pts[pts_counter].X);&lt;br /&gt;                    dlc.Ords[_k + 1] = System.Convert.ToDecimal(pts[pts_counter].Y);&lt;br /&gt;                    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                        dlc.Ords[_k + 2] = System.Convert.ToDecimal(pts[pts_counter].Z);&lt;br /&gt;                    _k = _k + len;&lt;br /&gt;                    pts_counter = pts_counter + 1;&lt;br /&gt;                }&lt;br /&gt;                dl.SubComponents.Add(dlc);&lt;br /&gt;            }&lt;br /&gt;            else if (hasBulgesCount == pts.Length - 1)&lt;br /&gt;            {&lt;br /&gt;                dlc.Etype = DrawAbleSubComponentEType.SimpleLineAllCurves;&lt;br /&gt;                int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;&lt;br /&gt;                dlc.Ords = new decimal[(len * pts.Length) + (hasBulgesCount * len)];&lt;br /&gt;                int ords_counter = 0;&lt;br /&gt;                Point3d arc_endpoint;&lt;br /&gt;&lt;br /&gt;                for (int j = 0; j &lt; pts.Length; j++)&lt;br /&gt;                {&lt;br /&gt;                    double theBulge = blgs[j];&lt;br /&gt;                    arc_endpoint = pts[j + 1];&lt;br /&gt;                    CircularArc2d ca2d = new CircularArc2d(&lt;br /&gt;                        new Point2d(pts[j].X, pts[j].Y),&lt;br /&gt;                        new Point2d(arc_endpoint.X, arc_endpoint.Y), theBulge, false);&lt;br /&gt;&lt;br /&gt;                    Interval interval_of_arc = ca2d.GetInterval();&lt;br /&gt;                    Point2d somePointOnArc = ca2d.EvaluatePoint(interval_of_arc.Element / 2);&lt;br /&gt;                    //Start&lt;br /&gt;                    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].X);&lt;br /&gt;                    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Y);&lt;br /&gt;                    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);&lt;br /&gt;                    //Center point on arc&lt;br /&gt;                    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(somePointOnArc.X);&lt;br /&gt;                    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(somePointOnArc.Y);&lt;br /&gt;                    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);&lt;br /&gt;&lt;br /&gt;                    //Because of LOOK-AHEAD we now check for the end&lt;br /&gt;                    if (j == (pts.Length - 2))&lt;br /&gt;                    {&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(arc_endpoint.X);&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(arc_endpoint.Y);&lt;br /&gt;                        if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                            dlc.Ords[ords_counter++] = System.Convert.ToDecimal(arc_endpoint.Z);&lt;br /&gt;                        j = pts.Length; //End the loop&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                dl.SubComponents.Add(dlc);&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                //DIM_ELEMENTS are required&lt;br /&gt;                dlc.Etype = DrawAbleSubComponentEType.CompoundLine;&lt;br /&gt;                int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;&lt;br /&gt;                dlc.Ords = new decimal[(len * pts.Length) + (hasBulgesCount * len)];&lt;br /&gt;                int ords_counter = 0;&lt;br /&gt;                Point3d arc_endpoint;&lt;br /&gt;&lt;br /&gt;                TriInts elmHeader = new TriInts(ords_counter, SDO.BasicETYPE(DrawAbleSubComponentEType.CompoundLine), 0);&lt;br /&gt;                List&lt;TriInts&gt; elmList = new List&lt;TriInts&gt;();&lt;br /&gt;                TriInts wrkrElm = null;&lt;br /&gt;                int nxtINTERP = 0;&lt;br /&gt;                int lstINTERP = 0;&lt;br /&gt;                for (int j = 0; j &lt; pts.Length; j++)&lt;br /&gt;                {&lt;br /&gt;                    if (j &lt; pts.Length - 1)&lt;br /&gt;                        nxtINTERP = (blgs[j] == 0.0) ? (int)SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleLine) : (int)SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleLineAllCurves);&lt;br /&gt;&lt;br /&gt;                    if (lstINTERP != nxtINTERP)&lt;br /&gt;                    {&lt;br /&gt;                        if (wrkrElm != null)&lt;br /&gt;                            elmList.Add(wrkrElm);&lt;br /&gt;                        wrkrElm = new TriInts(ords_counter, SDO.BasicETYPE(DrawAbleSubComponentEType.SimpleLineAllCurves), nxtINTERP);&lt;br /&gt;                        lstINTERP = nxtINTERP;&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;                    double theBulge = blgs[j];&lt;br /&gt;                    if (theBulge != 0.0)&lt;br /&gt;                    {&lt;br /&gt;                        arc_endpoint = pts[j + 1];&lt;br /&gt;                        CircularArc2d ca2d = new CircularArc2d(&lt;br /&gt;                            new Point2d(pts[j].X, pts[j].Y),&lt;br /&gt;                            new Point2d(arc_endpoint.X, arc_endpoint.Y), theBulge, false);&lt;br /&gt;&lt;br /&gt;                        Interval interval_of_arc = ca2d.GetInterval();&lt;br /&gt;                        Point2d somePointOnArc = ca2d.EvaluatePoint(interval_of_arc.Element / 2);&lt;br /&gt;                        //Start&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].X);&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Y);&lt;br /&gt;                        if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                            dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);&lt;br /&gt;                        //Center point on arc&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(somePointOnArc.X);&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(somePointOnArc.Y);&lt;br /&gt;                        if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                            dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);&lt;br /&gt;                    }&lt;br /&gt;                    else&lt;br /&gt;                    {&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].X);&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Y);&lt;br /&gt;                        if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                            dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;                }//for loop&lt;br /&gt;                elmList.Add(wrkrElm);&lt;br /&gt;                elmHeader.INTERP = elmList.Count;&lt;br /&gt;                dlc.Elem = new int[(elmList.Count + 1) * 3];&lt;br /&gt;                int cntr = 0;&lt;br /&gt;                dlc.Elem[cntr++] = elmHeader.OFFSET;&lt;br /&gt;                dlc.Elem[cntr++] = elmHeader.ETYPE;&lt;br /&gt;                dlc.Elem[cntr++] = elmHeader.INTERP;&lt;br /&gt;                for (int _i = 0; _i &lt; elmList.Count; _i++)&lt;br /&gt;                {&lt;br /&gt;                    dlc.Elem[cntr++] = elmList[_i].OFFSET;&lt;br /&gt;                    dlc.Elem[cntr++] = elmList[_i].ETYPE;&lt;br /&gt;                    dlc.Elem[cntr++] = elmList[_i].INTERP;&lt;br /&gt;                }&lt;br /&gt;                dl.SubComponents.Add(dlc);&lt;br /&gt;            }&lt;br /&gt;            return dl;&lt;br /&gt;        }&lt;br /&gt;        public static DrawAble LineCurveDrawAbleFromArc(Arc a, int _dimensionality)&lt;br /&gt;        {&lt;br /&gt;            DrawAble d = new DrawAble(DrawAbleType.Line, _dimensionality);&lt;br /&gt;            DrawAbleSubComponent dc = new DrawAbleSubComponent();&lt;br /&gt;            dc.Etype = DrawAbleSubComponentEType.SimpleLineAllCurves;&lt;br /&gt;            int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;&lt;br /&gt;            dc.Ords = new decimal[len * 3];&lt;br /&gt;            double length = a.GetDistAtPoint(a.EndPoint);&lt;br /&gt;            Point3d mid = a.GetPointAtDist(length / 2.0);&lt;br /&gt;            int ords_counter = 0;&lt;br /&gt;            //Start&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(a.StartPoint.X);&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(a.StartPoint.Y);&lt;br /&gt;            if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                dc.Ords[ords_counter++] = System.Convert.ToDecimal(a.StartPoint.Z);&lt;br /&gt;            //Mid&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(mid.X);&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(mid.Y);&lt;br /&gt;            if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                dc.Ords[ords_counter++] = System.Convert.ToDecimal(mid.Z);&lt;br /&gt;            //End&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(a.EndPoint.X);&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(a.EndPoint.Y);&lt;br /&gt;            if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                dc.Ords[ords_counter++] = System.Convert.ToDecimal(a.EndPoint.Z);&lt;br /&gt;            d.SubComponents.Add(dc);&lt;br /&gt;&lt;br /&gt;            return d;&lt;br /&gt;        }&lt;br /&gt;        public static DrawAble LineCurveDrawAbleFromLine(Line l, int _dimensionality)&lt;br /&gt;        {&lt;br /&gt;            DrawAble d = new DrawAble(DrawAbleType.Line, _dimensionality);&lt;br /&gt;            DrawAbleSubComponent dc = new DrawAbleSubComponent();&lt;br /&gt;            dc.Etype = DrawAbleSubComponentEType.SimpleLine;&lt;br /&gt;            int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;&lt;br /&gt;            dc.Ords = new decimal[len * 2];&lt;br /&gt;            int ords_counter = 0;&lt;br /&gt;            //Start&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(l.StartPoint.X);&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(l.StartPoint.Y);&lt;br /&gt;            if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                dc.Ords[ords_counter++] = System.Convert.ToDecimal(l.StartPoint.Z);&lt;br /&gt;            //End&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(l.EndPoint.X);&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(l.EndPoint.Y);&lt;br /&gt;            if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                dc.Ords[ords_counter++] = System.Convert.ToDecimal(l.EndPoint.Z);&lt;br /&gt;            d.SubComponents.Add(dc);&lt;br /&gt;&lt;br /&gt;            return d;&lt;br /&gt;        }&lt;br /&gt;        public static DrawAble LineCurveDrawAbleFromCircle(Circle circ, int _dimensionality)&lt;br /&gt;        {&lt;br /&gt;            DrawAble d = new DrawAble(DrawAbleType.Line, _dimensionality);&lt;br /&gt;            DrawAbleSubComponent dc = new DrawAbleSubComponent();&lt;br /&gt;            dc.Etype = DrawAbleSubComponentEType.SimpleLineAllCurves;&lt;br /&gt;            int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? 15 : 10;         &lt;br /&gt;            dc.Ords = new decimal[len];&lt;br /&gt;            int ords_counter = 0;            &lt;br /&gt;            double length = circ.Circumference;&lt;br /&gt;            Point3d firstarc_endpoint = circ.GetPointAtDist(length / 2.0);&lt;br /&gt;            Point3d firstarc_midpoint = circ.GetPointAtDist((length / 2.0) / 2.0);&lt;br /&gt;            Point3d secondarc_midpoint = circ.GetPointAtDist(length * .75);&lt;br /&gt;            //Start&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(circ.StartPoint.X);&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(circ.StartPoint.Y);&lt;br /&gt;            if (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                dc.Ords[ords_counter++] = System.Convert.ToDecimal(circ.StartPoint.Z);&lt;br /&gt;            //mid 1&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(firstarc_midpoint.X);&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(firstarc_midpoint.Y);&lt;br /&gt;            if (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                dc.Ords[ords_counter++] = System.Convert.ToDecimal(firstarc_midpoint.Z);&lt;br /&gt;            //End&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(firstarc_endpoint.X);&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(firstarc_endpoint.Y);&lt;br /&gt;            if (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                dc.Ords[ords_counter++] = System.Convert.ToDecimal(firstarc_endpoint.Z);&lt;br /&gt;            //mid 2&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(secondarc_midpoint.X);&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(secondarc_midpoint.Y);&lt;br /&gt;            if (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                dc.Ords[ords_counter++] = System.Convert.ToDecimal(secondarc_midpoint.Z);&lt;br /&gt;            //End&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(circ.EndPoint.X);&lt;br /&gt;            dc.Ords[ords_counter++] = System.Convert.ToDecimal(circ.EndPoint.Y);&lt;br /&gt;            if (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                dc.Ords[ords_counter++] = System.Convert.ToDecimal(circ.EndPoint.Z);&lt;br /&gt;&lt;br /&gt;            d.SubComponents.Add(dc);&lt;br /&gt;&lt;br /&gt;            return d;&lt;br /&gt;        }&lt;br /&gt;        //&lt;br /&gt;        // SURFACES&lt;br /&gt;        //&lt;br /&gt;        public static DrawAble PolygonDrawAbleFromMPolygon(MPolygon mpoly, int _dimensionality)&lt;br /&gt;        {&lt;br /&gt;            DrawAble dl = new DrawAble(DrawAbleType.Surface, _dimensionality);&lt;br /&gt;            Point3dCollection p3dColl = new Point3dCollection();&lt;br /&gt;            LoopDirection loopdirection;&lt;br /&gt;            int ords_counter = 0;                           // The total ordinates in the array&lt;br /&gt;            int hasBulgesCount = 0;&lt;br /&gt;            int loops = mpoly.NumMPolygonLoops;&lt;br /&gt;            for (int i = 0; i &lt; loops; i++)&lt;br /&gt;            {&lt;br /&gt;                // Gather up points and bulges for this loop&lt;br /&gt;                MPolygonLoop mPolygonLoop = mpoly.GetMPolygonLoopAt(i);&lt;br /&gt;                loopdirection = mpoly.GetLoopDirection(i);&lt;br /&gt;                hasBulgesCount = 0;&lt;br /&gt;                ords_counter = 0;&lt;br /&gt;                // Remove duplicate verticies&lt;br /&gt;                for (int d = 1; d &lt; mPolygonLoop.Count - 1; d++)&lt;br /&gt;                {&lt;br /&gt;                    if (mPolygonLoop[d].Vertex.IsEqualTo(mPolygonLoop[d + 1].Vertex))&lt;br /&gt;                    {&lt;br /&gt;                        mPolygonLoop.RemoveAt(d + 1);&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                //&lt;br /&gt;                Point3d[] pts = new Point3d[mPolygonLoop.Count];&lt;br /&gt;                double[] blgs = new double[mPolygonLoop.Count];&lt;br /&gt;                for (int z = 0; z &lt; mPolygonLoop.Count; z++)&lt;br /&gt;                {&lt;br /&gt;                    if (z == mPolygonLoop.Count - 1)&lt;br /&gt;                    {&lt;br /&gt;                        pts[z] = pts[0];&lt;br /&gt;                    }&lt;br /&gt;                    else&lt;br /&gt;                    {&lt;br /&gt;                        double X = Math.Round(mPolygonLoop[z].Vertex.X, 10, MidpointRounding.AwayFromZero);&lt;br /&gt;                        double Y = Math.Round(mPolygonLoop[z].Vertex.Y, 10, MidpointRounding.AwayFromZero);&lt;br /&gt;                        double Z = Math.Round(mpoly.Elevation, 10, MidpointRounding.AwayFromZero);&lt;br /&gt;                        pts[z] = new Point3d(X, Y, Z);&lt;br /&gt;                    }&lt;br /&gt;                    blgs[z] = mPolygonLoop[z].Bulge;&lt;br /&gt;                    if (blgs[z] != 0.0)&lt;br /&gt;                        hasBulgesCount = hasBulgesCount + 1;&lt;br /&gt;                }&lt;br /&gt;                //&lt;br /&gt;                // Suspect code here ......&lt;br /&gt;                //&lt;br /&gt;                if (blgs[0] == blgs[mPolygonLoop.Count - 1] &amp;&amp; blgs[0] != 0.0)&lt;br /&gt;                {&lt;br /&gt;                    blgs[mPolygonLoop.Count - 1] = 0.0;&lt;br /&gt;                    hasBulgesCount--;&lt;br /&gt;                }&lt;br /&gt;                //&lt;br /&gt;                //DO THE STUFF&lt;br /&gt;                //&lt;br /&gt;                DrawAbleSubComponent dlc = new DrawAbleSubComponent();&lt;br /&gt;                TriInts headerElem = new TriInts(ords_counter, 0, 0);&lt;br /&gt;                if (hasBulgesCount == 0)&lt;br /&gt;                {&lt;br /&gt;                    headerElem.INTERP = SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine);&lt;br /&gt;                }&lt;br /&gt;                //else if (hasBulgesCount == pts.Length)&lt;br /&gt;                else if (hasBulgesCount == pts.Length - 1)&lt;br /&gt;                {&lt;br /&gt;                    headerElem.INTERP = SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceInnerRingAllCurves);&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                if (loopdirection == LoopDirection.Exterior)&lt;br /&gt;                {&lt;br /&gt;                    if (headerElem.INTERP == SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine) ||&lt;br /&gt;                        headerElem.INTERP == SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceOuterRingAllCurves))&lt;br /&gt;                    {&lt;br /&gt;                        headerElem.ETYPE = SDO.BasicETYPE(DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine);&lt;br /&gt;                        if (headerElem.INTERP == SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine))&lt;br /&gt;                            dlc.Etype = DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine;&lt;br /&gt;                        else&lt;br /&gt;                            dlc.Etype = DrawAbleSubComponentEType.SimpleSurfaceOuterRingAllCurves;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                else&lt;br /&gt;                {&lt;br /&gt;&lt;br /&gt;                    if (headerElem.INTERP == SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine) ||&lt;br /&gt;                        headerElem.INTERP == SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceInnerRingAllCurves))&lt;br /&gt;                    {&lt;br /&gt;                        headerElem.ETYPE = SDO.BasicETYPE(DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine);&lt;br /&gt;                        if (headerElem.INTERP == SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine))&lt;br /&gt;                            dlc.Etype = DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine;&lt;br /&gt;                        else&lt;br /&gt;                            dlc.Etype = DrawAbleSubComponentEType.SimpleSurfaceInnerRingAllCurves;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                // If we have not set the etype it must be a 1005 0R 2005 - compound polygon&lt;br /&gt;                if (headerElem.ETYPE == 0 &amp;&amp; hasBulgesCount &gt; 0)&lt;br /&gt;                {&lt;br /&gt;                    if (loopdirection == LoopDirection.Exterior)&lt;br /&gt;                    {&lt;br /&gt;                        headerElem.ETYPE = SDO.BasicETYPE(DrawAbleSubComponentEType.CompoundSurfaceOuterRingLine);&lt;br /&gt;                        dlc.Etype = DrawAbleSubComponentEType.CompoundSurfaceOuterRingLine;&lt;br /&gt;                    }&lt;br /&gt;                    else&lt;br /&gt;                    {&lt;br /&gt;                        headerElem.ETYPE = SDO.BasicETYPE(DrawAbleSubComponentEType.CompoundSurfaceInnerRingLine);&lt;br /&gt;                        dlc.Etype = DrawAbleSubComponentEType.CompoundSurfaceInnerRingLine;&lt;br /&gt;                    }&lt;br /&gt;                    headerElem.INTERP = 0; // to be set later with count&lt;br /&gt;                }&lt;br /&gt;                //Now we are ready to build the elem and ords&lt;br /&gt;                int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;&lt;br /&gt;                dlc.Ords = new decimal[(len * pts.Length) + (hasBulgesCount * len)];&lt;br /&gt;                List&lt;TriInts&gt; elmList = new List&lt;TriInts&gt;();&lt;br /&gt;                TriInts wrkrElm = null;&lt;br /&gt;                int nxtINTERP = 0;&lt;br /&gt;                int lstINTERP = 0;&lt;br /&gt;                Point3d arc_endpoint;&lt;br /&gt;                for (int j = 0; j &lt; pts.Length; j++)&lt;br /&gt;                {&lt;br /&gt;                    if (j &lt; pts.Length - 1)&lt;br /&gt;                        nxtINTERP = (blgs[j] == 0.0) ? SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleLine) : SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleLineAllCurves);&lt;br /&gt;&lt;br /&gt;                    if (lstINTERP != nxtINTERP)&lt;br /&gt;                    {&lt;br /&gt;                        if (wrkrElm != null)&lt;br /&gt;                            elmList.Add(wrkrElm);&lt;br /&gt;                        wrkrElm = new TriInts(ords_counter,&lt;br /&gt;                           SDO.BasicETYPE((blgs[j] == 0.0) ? DrawAbleSubComponentEType.SimpleLine : DrawAbleSubComponentEType.SimpleLineAllCurves),&lt;br /&gt;                           nxtINTERP);&lt;br /&gt;                        lstINTERP = nxtINTERP;&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;                    double theBulge = blgs[j];&lt;br /&gt;                    if (theBulge != 0.0)&lt;br /&gt;                    {&lt;br /&gt;                        arc_endpoint = pts[j + 1];&lt;br /&gt;                        CircularArc2d ca2d = new CircularArc2d(&lt;br /&gt;                            new Point2d(pts[j].X, pts[j].Y),&lt;br /&gt;                            new Point2d(arc_endpoint.X, arc_endpoint.Y), theBulge, false);&lt;br /&gt;&lt;br /&gt;                        Interval interval_of_arc = ca2d.GetInterval();&lt;br /&gt;                        Point2d somePointOnArc = ca2d.EvaluatePoint(interval_of_arc.Element / 2);&lt;br /&gt;                        //Start&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].X);&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Y);&lt;br /&gt;                        if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                            dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);&lt;br /&gt;                        //Center point on arc&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(somePointOnArc.X);&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(somePointOnArc.Y);&lt;br /&gt;                        if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                            dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);&lt;br /&gt;                    }&lt;br /&gt;                    else&lt;br /&gt;                    {&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].X);&lt;br /&gt;                        dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Y);&lt;br /&gt;                        if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                            dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;                }//for loop of ordinates&lt;br /&gt;                int elem_cntr = 0;&lt;br /&gt;                if (headerElem.ETYPE == SDO.BasicETYPE(DrawAbleSubComponentEType.CompoundSurfaceInnerRingLine) ||&lt;br /&gt;                    headerElem.ETYPE == SDO.BasicETYPE(DrawAbleSubComponentEType.CompoundSurfaceOuterRingLine))&lt;br /&gt;                {&lt;br /&gt;                    //Add our last worker element&lt;br /&gt;                    elmList.Add(wrkrElm);&lt;br /&gt;                    //Update the count in the header&lt;br /&gt;                    headerElem.INTERP = elmList.Count;&lt;br /&gt;                    //Dimension the array = element list count +  one(1) for header "times" three(3)&lt;br /&gt;                    dlc.Elem = new int[(elmList.Count + 1) * 3];&lt;br /&gt;                    dlc.Elem[elem_cntr++] = headerElem.OFFSET;&lt;br /&gt;                    dlc.Elem[elem_cntr++] = headerElem.ETYPE;&lt;br /&gt;                    dlc.Elem[elem_cntr++] = headerElem.INTERP;&lt;br /&gt;                    for (int _i = 0; _i &lt; elmList.Count; _i++)&lt;br /&gt;                    {&lt;br /&gt;                        dlc.Elem[elem_cntr++] = elmList[_i].OFFSET;&lt;br /&gt;                        dlc.Elem[elem_cntr++] = elmList[_i].ETYPE;&lt;br /&gt;                        dlc.Elem[elem_cntr++] = elmList[_i].INTERP;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                else&lt;br /&gt;                {&lt;br /&gt;                    dlc.Elem = new int[3];&lt;br /&gt;                    dlc.Elem[elem_cntr++] = headerElem.OFFSET;&lt;br /&gt;                    dlc.Elem[elem_cntr++] = headerElem.ETYPE;&lt;br /&gt;                    dlc.Elem[elem_cntr++] = headerElem.INTERP;&lt;br /&gt;                }&lt;br /&gt;                dl.SubComponents.Add(dlc);&lt;br /&gt;            }//next ring in the MPolygon&lt;br /&gt;&lt;br /&gt;            return dl;&lt;br /&gt;        }&lt;br /&gt;        //&lt;br /&gt;        // Returns: List&lt;DBPoint&gt;, DBPoint, Polyline, MPolygon&lt;br /&gt;        //&lt;br /&gt;        public static object DrawAbleDwgObj(DrawAble drawable)&lt;br /&gt;        {&lt;br /&gt;            bool firstPointFlag = false;&lt;br /&gt;            int IncrementFor3d = 0;&lt;br /&gt;            if (drawable.Dimensionality == MDADDrawAbles.DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                IncrementFor3d = 1;&lt;br /&gt;            MPolygon dbMpoly = null;&lt;br /&gt;            Polyline plineCurves = null;&lt;br /&gt;            Polyline plineCompound = null;&lt;br /&gt;            Polyline plineLine = null;&lt;br /&gt;            DBPoint dbPoint = null;&lt;br /&gt;            List&lt;DBPoint&gt; dbPointList = null;&lt;br /&gt;&lt;br /&gt;            //Turn the dim elements into triplets for easy use&lt;br /&gt;            List&lt;TriInts&gt; elmsList = null;&lt;br /&gt;            int CountOfComponents = drawable.SubComponents.Count;&lt;br /&gt;            foreach (DrawAbleSubComponent cmp in drawable.SubComponents)&lt;br /&gt;            {&lt;br /&gt;                if (cmp.Elem != null)&lt;br /&gt;                {&lt;br /&gt;                    elmsList = new List&lt;TriInts&gt;();&lt;br /&gt;                    for (int _i = 0; _i &lt; cmp.Elem.Length; )&lt;br /&gt;                    {&lt;br /&gt;                        TriInts t = new TriInts(cmp.Elem[_i + 0], cmp.Elem[_i + 1], cmp.Elem[_i + 2]);&lt;br /&gt;                        elmsList.Add(t);&lt;br /&gt;                        _i = _i + 3;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                else&lt;br /&gt;                    elmsList = null;&lt;br /&gt;                //Turn all the decimals into doubles&lt;br /&gt;                double[] ords = new double[cmp.Ords.Length];&lt;br /&gt;                for (int j = 0; j &lt; cmp.Ords.Length; j++)&lt;br /&gt;                    ords[j] = System.Convert.ToDouble(cmp.Ords[j]);&lt;br /&gt;&lt;br /&gt;                DrawAbleSubComponentEType etype = cmp.Etype;&lt;br /&gt;                firstPointFlag = false;&lt;br /&gt;&lt;br /&gt;                //&lt;br /&gt;                //Compound components&lt;br /&gt;                //These require a header and fixup of the components dim element array&lt;br /&gt;                //&lt;br /&gt;                if (cmp.Etype == DrawAbleSubComponentEType.CompoundLine ||&lt;br /&gt;                    cmp.Etype == DrawAbleSubComponentEType.CompoundSurfaceInnerRingLine ||&lt;br /&gt;                    cmp.Etype == DrawAbleSubComponentEType.CompoundSurfaceOuterRingLine)&lt;br /&gt;                {&lt;br /&gt;                    CircularArc2d ca2d;&lt;br /&gt;                    Point2d firstPoint2d = new Point2d();&lt;br /&gt;                    Point2d begPoint2d = new Point2d();&lt;br /&gt;                    Point2d arrowPoint2d, endPoint2d;&lt;br /&gt;&lt;br /&gt;                    plineCompound = new Polyline();&lt;br /&gt;&lt;br /&gt;                    //We know what it is because of Etype. We just really need the INTERPs and OFFSETs. Skip to one(1)&lt;br /&gt;                    for (int _k = 1; _k &lt; elmsList.Count; )&lt;br /&gt;                    {&lt;br /&gt;                        TriInts t = elmsList[_k]; int OFFSET = t.OFFSET; int ETYPE = t.ETYPE; int INTERP = t.INTERP;&lt;br /&gt;                        int nxtOFFSET = 0;&lt;br /&gt;                        if (_k &lt; elmsList.Count - 1)&lt;br /&gt;                            nxtOFFSET = elmsList[_k + 1].OFFSET;&lt;br /&gt;                        else&lt;br /&gt;                            nxtOFFSET = ords.Length;&lt;br /&gt;                        for (int x = OFFSET; x &lt; nxtOFFSET; )&lt;br /&gt;                        {&lt;br /&gt;                            double bulgeValue = 0.0;&lt;br /&gt;                            if (firstPointFlag == false) { firstPoint2d = new Point2d(ords[x], ords[x + 1]); firstPointFlag = true; }&lt;br /&gt;                            if (INTERP == 2)&lt;br /&gt;                            {&lt;br /&gt;                                begPoint2d = new Point2d(ords[x++], ords[x++]); x = x + IncrementFor3d;&lt;br /&gt;                                //Only if we are not at the end. We ended the line with an arc.&lt;br /&gt;                                if (x &lt; nxtOFFSET)&lt;br /&gt;                                {&lt;br /&gt;                                    arrowPoint2d = new Point2d(ords[x++], ords[x++]); x = x + IncrementFor3d;&lt;br /&gt;                                    endPoint2d = new Point2d(ords[x], ords[x + 1]);&lt;br /&gt;                                    ca2d = new CircularArc2d(begPoint2d, arrowPoint2d, endPoint2d);&lt;br /&gt;                                    bulgeValue = GetBulge2d(ca2d);&lt;br /&gt;                                    ca2d.Dispose();&lt;br /&gt;                                }&lt;br /&gt;                                plineCompound.AddVertexAt(plineCompound.NumberOfVertices, begPoint2d, bulgeValue, 0, 0);&lt;br /&gt;                                if (drawable.Dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                                    plineCompound.Elevation = ords[x - 1];&lt;br /&gt;                            }&lt;br /&gt;                            else&lt;br /&gt;                            {&lt;br /&gt;                                begPoint2d = new Point2d(ords[x++], ords[x++]); x = x + IncrementFor3d;&lt;br /&gt;                                plineCompound.AddVertexAt(plineCompound.NumberOfVertices, begPoint2d, 0.0, 0.0, 0.0);&lt;br /&gt;                                if (drawable.Dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                                    plineCompound.Elevation = ords[x - 1];&lt;br /&gt;                            }&lt;br /&gt;                        }&lt;br /&gt;                        _k = _k + 1;&lt;br /&gt;                    }&lt;br /&gt;                    if (firstPoint2d == begPoint2d)&lt;br /&gt;                        plineCompound.Closed = true;&lt;br /&gt;&lt;br /&gt;                    if (cmp.Etype == DrawAbleSubComponentEType.CompoundSurfaceInnerRingLine ||&lt;br /&gt;                        cmp.Etype == DrawAbleSubComponentEType.CompoundSurfaceOuterRingLine)&lt;br /&gt;                    {&lt;br /&gt;                        if (dbMpoly == null)&lt;br /&gt;                        {&lt;br /&gt;                            dbMpoly = new MPolygon();&lt;br /&gt;                        }&lt;br /&gt;                        dbMpoly.AppendLoopFromBoundary(plineCompound, false, 0.005);&lt;br /&gt;                        dbMpoly.BalanceTree();&lt;br /&gt;                        plineCompound.Dispose();&lt;br /&gt;                        plineCompound = null;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                //&lt;br /&gt;                //Point and PointCluster&lt;br /&gt;                //&lt;br /&gt;                if (cmp.Etype == DrawAbleSubComponentEType.Point)&lt;br /&gt;                {&lt;br /&gt;                    Point3d p3d;&lt;br /&gt;                    if (IncrementFor3d == 1)&lt;br /&gt;                        p3d = new Point3d(ords[0], ords[1], ords[2]);&lt;br /&gt;                    else&lt;br /&gt;                        p3d = new Point3d(ords[0], ords[1], 0.0);&lt;br /&gt;                    dbPoint = new DBPoint(p3d);&lt;br /&gt;                }&lt;br /&gt;                else if (cmp.Etype == DrawAbleSubComponentEType.PointCluster)&lt;br /&gt;                    {&lt;br /&gt;                        Point3d p3d;&lt;br /&gt;                        dbPointList = new List&lt;DBPoint&gt;();&lt;br /&gt;&lt;br /&gt;                        for (int _x = 0; _x &lt; ords.Length; )&lt;br /&gt;                        {&lt;br /&gt;                            if (IncrementFor3d == 1)&lt;br /&gt;                                p3d = new Point3d(ords[_x++], ords[_x++], ords[_x++]);&lt;br /&gt;                            else&lt;br /&gt;                                p3d = new Point3d(ords[_x++], ords[_x++], 0.0);&lt;br /&gt;                            dbPoint = new DBPoint(p3d);&lt;br /&gt;                            dbPointList.Add(dbPoint);&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;                //&lt;br /&gt;                //Simple lines&lt;br /&gt;                //&lt;br /&gt;                if (cmp.Etype == DrawAbleSubComponentEType.SimpleLine ||&lt;br /&gt;                    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine ||&lt;br /&gt;                    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine)&lt;br /&gt;                {&lt;br /&gt;                    Point2d begPoint2d = new Point2d();&lt;br /&gt;                    Point2d firstPoint2d = new Point2d();&lt;br /&gt;                    plineLine = new Polyline();&lt;br /&gt;&lt;br /&gt;                    for (int _x = 0; _x &lt; ords.Length; )&lt;br /&gt;                    {&lt;br /&gt;                        if (firstPointFlag == false) { firstPoint2d = new Point2d(ords[0], ords[1]); firstPointFlag = true; }&lt;br /&gt;                        begPoint2d = new Point2d(ords[_x++], ords[_x++]); _x = _x + IncrementFor3d;&lt;br /&gt;                        plineLine.AddVertexAt(plineLine.NumberOfVertices, begPoint2d, 0.0, 0.0, 0.0);&lt;br /&gt;                        if (drawable.Dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                            plineLine.Elevation = ords[_x - 1];&lt;br /&gt;                    }&lt;br /&gt;                    if (firstPoint2d == begPoint2d)&lt;br /&gt;                        plineLine.Closed = true;&lt;br /&gt;&lt;br /&gt;                    if (cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine ||&lt;br /&gt;                        cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine)&lt;br /&gt;                    {&lt;br /&gt;                        if (dbMpoly == null)&lt;br /&gt;                        {&lt;br /&gt;                            dbMpoly = new MPolygon();&lt;br /&gt;                        }&lt;br /&gt;                        dbMpoly.AppendLoopFromBoundary(plineLine, false, 0.005);&lt;br /&gt;                        dbMpoly.BalanceTree();&lt;br /&gt;                        plineLine.Dispose();&lt;br /&gt;                        plineLine = null;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                //&lt;br /&gt;                //Simple Curves&lt;br /&gt;                //&lt;br /&gt;                if (cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingAllCurves ||&lt;br /&gt;                    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingAllCurves ||&lt;br /&gt;                    cmp.Etype == DrawAbleSubComponentEType.SimpleLineAllCurves)&lt;br /&gt;                {&lt;br /&gt;                    CircularArc2d ca2d;&lt;br /&gt;                    Point2d begPoint2d = new Point2d();&lt;br /&gt;                    Point2d firstPoint2d = new Point2d();&lt;br /&gt;                    Point2d arrowPoint2d, endPoint2d;&lt;br /&gt;                    plineCurves = new Polyline();&lt;br /&gt;                    //We know what it is because of Etype. We just really need the INTERPs and OFFSETs. Skip to one(1)&lt;br /&gt;                    for (int _x = 0; _x &lt; ords.Length; )&lt;br /&gt;                    {&lt;br /&gt;                        if (firstPointFlag == false) { firstPoint2d = new Point2d(ords[0], ords[1]); firstPointFlag = true; }&lt;br /&gt;                        begPoint2d = new Point2d(ords[_x++], ords[_x++]); _x = _x + IncrementFor3d;&lt;br /&gt;                        double bulgeValue = 0.0;&lt;br /&gt;                        if (_x &lt; ords.Length)&lt;br /&gt;                        {&lt;br /&gt;                            arrowPoint2d = new Point2d(ords[_x++], ords[_x++]); _x = _x + IncrementFor3d;&lt;br /&gt;                            endPoint2d = new Point2d(ords[_x], ords[_x + 1]);&lt;br /&gt;                            ca2d = new CircularArc2d(begPoint2d, arrowPoint2d, endPoint2d);&lt;br /&gt;                            bulgeValue = GetBulge2d(ca2d);&lt;br /&gt;                            ca2d.Dispose();&lt;br /&gt;                        }&lt;br /&gt;                        plineCurves.AddVertexAt(plineCurves.NumberOfVertices, begPoint2d, bulgeValue, 0, 0);&lt;br /&gt;                        if (drawable.Dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                            plineCurves.Elevation = ords[_x - 1];                       &lt;br /&gt;                    }&lt;br /&gt;                    if (firstPoint2d == begPoint2d)&lt;br /&gt;                        plineCurves.Closed = true;&lt;br /&gt;&lt;br /&gt;                    if (cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingAllCurves ||&lt;br /&gt;                        cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingAllCurves)&lt;br /&gt;                    {&lt;br /&gt;                        if (dbMpoly == null)&lt;br /&gt;                        {&lt;br /&gt;                            dbMpoly = new MPolygon();&lt;br /&gt;                        }&lt;br /&gt;                        dbMpoly.AppendLoopFromBoundary(plineCurves, false, 0.005);&lt;br /&gt;                        dbMpoly.BalanceTree();&lt;br /&gt;                        plineCurves.Dispose();&lt;br /&gt;                        plineCurves = null;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                //&lt;br /&gt;                // Circle&lt;br /&gt;                //&lt;br /&gt;                if (cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingCircle ||&lt;br /&gt;                    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingCircle)&lt;br /&gt;                {&lt;br /&gt;                    Circle circleSurf = null;&lt;br /&gt;                    Point2d a = new Point2d(ords[0], ords[1]);&lt;br /&gt;                    Point2d b = new Point2d(ords[2 + IncrementFor3d], ords[3 + IncrementFor3d]);&lt;br /&gt;                    Point2d c = new Point2d(ords[4 + IncrementFor3d + IncrementFor3d], ords[5 + IncrementFor3d + IncrementFor3d]);&lt;br /&gt;                    double A = b.X - a.X;&lt;br /&gt;                    double B = b.Y - a.Y;&lt;br /&gt;                    double C = c.X - a.X;&lt;br /&gt;                    double D = c.Y - a.Y;&lt;br /&gt;&lt;br /&gt;                    double E = A * (a.X + b.X) + B * (a.Y + b.Y);&lt;br /&gt;                    double F = C * (a.X + c.X) + D * (a.Y + c.Y);&lt;br /&gt;                    double G = 2.0 * (A * (c.Y - b.Y) - B * (c.X - b.X));&lt;br /&gt;&lt;br /&gt;                    if (G != 0)&lt;br /&gt;                    {&lt;br /&gt;                        double pX = (D * E - B * F) / G;&lt;br /&gt;                        double pY = (A * F - C * E) / G;&lt;br /&gt;&lt;br /&gt;                        // r^2 = (a.X - pX) ^ 2.0 + (a.Y - pY) ^ 2.0&lt;br /&gt;                        double radiusSqd = Math.Pow((a.X - pX), 2.0) + Math.Pow((a.Y - pY), 2.0);&lt;br /&gt;                        double radius = Math.Sqrt(radiusSqd);&lt;br /&gt;&lt;br /&gt;                        Point3d p3d_center = new Point3d(pX, pY, 0.0);&lt;br /&gt;                        circleSurf = new Circle(p3d_center, new Vector3d(0.0, 0.0, 1.0), radius);&lt;br /&gt;                    }&lt;br /&gt;                    if (dbMpoly == null)&lt;br /&gt;                    {&lt;br /&gt;                        dbMpoly = new MPolygon();&lt;br /&gt;                    }&lt;br /&gt;                    dbMpoly.AppendLoopFromBoundary(circleSurf, false, 0.005);&lt;br /&gt;                    dbMpoly.BalanceTree();&lt;br /&gt;                    circleSurf.Dispose();&lt;br /&gt;                    circleSurf = null;&lt;br /&gt;                }&lt;br /&gt;                //&lt;br /&gt;                //Rectangle&lt;br /&gt;                //&lt;br /&gt;                if (cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingRectangle ||&lt;br /&gt;                    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingRectangle)&lt;br /&gt;                {&lt;br /&gt;                    Polyline plineRect = new Polyline();&lt;br /&gt;                    Point2d sw2d = new Point2d(ords[0], ords[1]);&lt;br /&gt;                    Point2d se2d = new Point2d(ords[2 + IncrementFor3d], ords[1]);&lt;br /&gt;                    Point2d ne2d = new Point2d(ords[2 + IncrementFor3d], ords[3 + IncrementFor3d]);&lt;br /&gt;                    Point2d nw2d = new Point2d(ords[0], ords[3 + IncrementFor3d]);&lt;br /&gt;                    Point2d closer2d = new Point2d(ords[0], ords[1]);&lt;br /&gt;                    plineRect.AddVertexAt(plineRect.NumberOfVertices, sw2d, 0.0, 0.0, 0.0);&lt;br /&gt;                    plineRect.AddVertexAt(plineRect.NumberOfVertices, se2d, 0.0, 0.0, 0.0);&lt;br /&gt;                    plineRect.AddVertexAt(plineRect.NumberOfVertices, ne2d, 0.0, 0.0, 0.0);&lt;br /&gt;                    plineRect.AddVertexAt(plineRect.NumberOfVertices, nw2d, 0.0, 0.0, 0.0);&lt;br /&gt;                    plineRect.AddVertexAt(plineRect.NumberOfVertices, closer2d, 0.0, 0.0, 0.0);&lt;br /&gt;                    plineRect.Closed = true;&lt;br /&gt;                    if (drawable.Dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)&lt;br /&gt;                        plineRect.Elevation = ords[2];&lt;br /&gt;                    if (dbMpoly == null)&lt;br /&gt;                    {&lt;br /&gt;                        dbMpoly = new MPolygon();&lt;br /&gt;                    }&lt;br /&gt;                    dbMpoly.AppendLoopFromBoundary(plineRect, false, 0.005);&lt;br /&gt;                    dbMpoly.BalanceTree();&lt;br /&gt;                    plineRect.Dispose();&lt;br /&gt;                    plineRect = null;&lt;br /&gt;                }&lt;br /&gt; &lt;br /&gt;            }//Do the next subcomponent&lt;br /&gt;            if (dbMpoly != null)&lt;br /&gt;                return (object)dbMpoly;&lt;br /&gt;            else if (dbPointList != null)&lt;br /&gt;                return (object)dbPointList;&lt;br /&gt;            else if (dbPoint != null)&lt;br /&gt;                return (object)dbPoint;&lt;br /&gt;            else if (plineLine != null)&lt;br /&gt;                return (object)plineLine;&lt;br /&gt;            else if (plineCurves != null)&lt;br /&gt;                return (object)plineCurves;&lt;br /&gt;            else if (plineCompound != null)&lt;br /&gt;                return (object)plineCompound;&lt;br /&gt;            else&lt;br /&gt;                return null;&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;    &lt;br /&gt;        public static double GetBulge2d(CircularArc2d ca2d)&lt;br /&gt;        {&lt;br /&gt;            double theBulge = 0.0;&lt;br /&gt;            if (ca2d.IsClockWise == true)&lt;br /&gt;            {&lt;br /&gt;                theBulge = -Math.Tan((ca2d.EndAngle - ca2d.StartAngle) / 4);&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                theBulge = Math.Tan((ca2d.EndAngle - ca2d.StartAngle) / 4);&lt;br /&gt;            }&lt;br /&gt;            return theBulge;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }//eoc DrawAbleDwg&lt;br /&gt;}//eons&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-5721137491880522431?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/5721137491880522431/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2009/11/vii-new-sdogeometry-autodesk-map3d-2010.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/5721137491880522431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/5721137491880522431'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2009/11/vii-new-sdogeometry-autodesk-map3d-2010.html' title='(VII) New SDO_GEOMETRY &lt;-&gt; Autodesk Map3d 2010'/><author><name>Dennis Jonio</name><uri>http://www.blogger.com/profile/14478827118325682041</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-841361800841411966</id><published>2009-11-17T12:30:00.003+01:00</published><updated>2009-11-17T12:36:31.890+01:00</updated><title type='text'>(VI) New SDO_GEOMETRY &lt;-&gt; Autodesk Map3d 2010</title><content type='html'>&lt;div&gt;Author: Jonio, Dennis&lt;/div&gt;&lt;br /&gt;The next on the list ...&lt;br /&gt;&lt;li&gt;Given some “DrawAble(s)” compose a NetSdoGeometry.sdogeometry.&lt;br /&gt;The method signature:&lt;br /&gt;public static sdogeometry &lt;strong&gt;SdoGeometryFromDrawAble(List&lt;DrawAble&gt; _drawables, int _lrs, int _srid)&lt;/strong&gt;&lt;br /&gt;If you recall the DrawAble holds the dimensionality so the Measure and the SRID had to be injected somewhere.&lt;br /&gt;Frankly the simplest of all the methods. Very straight forward implementaion.&lt;br /&gt;Maybe somewhat unusual here is that I made this a static method within the static utility class.&lt;br /&gt;&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;public static sdogeometry SdoGeometryFromDrawAble(List&lt;DrawAble&gt; _drawables, int _lrs, int _srid)&lt;br /&gt;{&lt;br /&gt; sdogeometry rtnval = null;&lt;br /&gt; List&lt;TriInts&gt; TotElms = new List&lt;TriInts&gt;();&lt;br /&gt; List&lt;decimal&gt; TotOrds = new List&lt;decimal&gt;();&lt;br /&gt; int CURRENT_OFFSET = 1;&lt;br /&gt; int CountOfItems = _drawables.Count;&lt;br /&gt; int CountOfComponents = 0;&lt;br /&gt;&lt;br /&gt; foreach (DrawAble drawable in _drawables)&lt;br /&gt; {&lt;br /&gt;  CountOfComponents = drawable.SubComponents.Count;&lt;br /&gt;  foreach (DrawAbleSubComponent cmp in drawable.SubComponents)&lt;br /&gt;  {&lt;br /&gt;   TriInts nxt_elem = null;&lt;br /&gt;   //&lt;br /&gt;   //Compound components&lt;br /&gt;   //&lt;br /&gt;   if (cmp.Etype == DrawAbleSubComponentEType.CompoundLine ||&lt;br /&gt;    cmp.Etype == DrawAbleSubComponentEType.CompoundSurfaceInnerRingLine ||&lt;br /&gt;    cmp.Etype == DrawAbleSubComponentEType.CompoundSurfaceOuterRingLine)&lt;br /&gt;   {&lt;br /&gt;    TriInts frst_head = new TriInts(CURRENT_OFFSET, BasicETYPE(cmp.Etype), (cmp.Elem.Length / 3) - 1);&lt;br /&gt;    TotElms.Add(frst_head);&lt;br /&gt;    for (int _k = 3; _k &lt; cmp.Elem.Length; )&lt;br /&gt;    {&lt;br /&gt;     TriInts nxt = new TriInts(CURRENT_OFFSET + cmp.Elem[_k + 0], cmp.Elem[_k + 1], cmp.Elem[_k + 2]);&lt;br /&gt;     TotElms.Add(nxt);&lt;br /&gt;     _k = _k + 3;&lt;br /&gt;    }&lt;br /&gt;    //Copy over the ordinates&lt;br /&gt;    for (int _i = 0; _i &lt; cmp.Ords.Length; _i++)&lt;br /&gt;     TotOrds.Add(cmp.Ords[_i]);&lt;br /&gt;&lt;br /&gt;    //We get out of the major loop here ... &lt;br /&gt;    //so we MUST set the CURRENT_OFFSET to the end of the ordinates + start point.&lt;br /&gt;    CURRENT_OFFSET = CURRENT_OFFSET + cmp.Ords.Length;&lt;br /&gt;    continue;&lt;br /&gt;   }&lt;br /&gt;   //&lt;br /&gt;   //Point and PointCluster&lt;br /&gt;   //&lt;br /&gt;   if (cmp.Etype == DrawAbleSubComponentEType.Point)&lt;br /&gt;   {&lt;br /&gt;    nxt_elem = new TriInts(CURRENT_OFFSET, BasicETYPE(cmp.Etype), BasicINTERPRETATION(cmp.Etype));&lt;br /&gt;    TotElms.Add(nxt_elem);&lt;br /&gt;    //Copy over the ordinates&lt;br /&gt;    for (int _i = 0; _i &lt; cmp.Ords.Length; _i++)&lt;br /&gt;     TotOrds.Add(cmp.Ords[_i]);&lt;br /&gt;    CURRENT_OFFSET = CURRENT_OFFSET + cmp.Ords.Length;&lt;br /&gt;    continue;&lt;br /&gt;   }&lt;br /&gt;   else if (cmp.Etype == DrawAbleSubComponentEType.PointCluster)&lt;br /&gt;   {&lt;br /&gt;    nxt_elem = new TriInts(CURRENT_OFFSET, BasicETYPE(cmp.Etype), cmp.Elem[2]);&lt;br /&gt;    TotElms.Add(nxt_elem);&lt;br /&gt;   }&lt;br /&gt;   //&lt;br /&gt;   //Lines&lt;br /&gt;   //&lt;br /&gt;   if (cmp.Etype == DrawAbleSubComponentEType.SimpleLine ||&lt;br /&gt;    cmp.Etype == DrawAbleSubComponentEType.SimpleLineAllCurves)&lt;br /&gt;   {&lt;br /&gt;    nxt_elem = new TriInts(CURRENT_OFFSET, BasicETYPE(cmp.Etype), BasicINTERPRETATION(cmp.Etype));&lt;br /&gt;    TotElms.Add(nxt_elem);&lt;br /&gt;   }&lt;br /&gt;   //&lt;br /&gt;   //Surface Stuff&lt;br /&gt;   //&lt;br /&gt;   if (cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingAllCurves ||&lt;br /&gt;    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingCircle ||&lt;br /&gt;    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine ||&lt;br /&gt;    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingRectangle ||&lt;br /&gt;    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingAllCurves ||&lt;br /&gt;    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingCircle ||&lt;br /&gt;    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine ||&lt;br /&gt;    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingRectangle&lt;br /&gt;    )&lt;br /&gt;   {&lt;br /&gt;    nxt_elem = new TriInts(CURRENT_OFFSET, BasicETYPE(cmp.Etype), BasicINTERPRETATION(cmp.Etype));&lt;br /&gt;    TotElms.Add(nxt_elem);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   //Copy over the ordinates and move the CURRENT OFFSET&lt;br /&gt;   for (int _i = 0; _i &lt; cmp.Ords.Length; _i++)&lt;br /&gt;    TotOrds.Add(cmp.Ords[_i]);&lt;br /&gt;   CURRENT_OFFSET = TotOrds.Count + 1;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; //&lt;br /&gt; // Now build the geometry object&lt;br /&gt; //&lt;br /&gt; if (TotElms.Count &gt; 0 &amp;&amp; TotOrds.Count &gt; 0)&lt;br /&gt; {&lt;br /&gt;  DrawAble drawable = _drawables[0];&lt;br /&gt;  decimal[] tmp_elems = new decimal[TotElms.Count * 3];&lt;br /&gt;  for (int _e = 0; _e &lt; TotElms.Count; _e++)&lt;br /&gt;  {&lt;br /&gt;   tmp_elems[_e * 3 + 0] = TotElms[_e].OFFSET;&lt;br /&gt;   tmp_elems[_e * 3 + 1] = TotElms[_e].ETYPE;&lt;br /&gt;   tmp_elems[_e * 3 + 2] = TotElms[_e].INTERP;&lt;br /&gt;  }&lt;br /&gt;  decimal[] tmp_ords = new decimal[TotOrds.Count];&lt;br /&gt;  tmp_ords = TotOrds.ToArray();&lt;br /&gt;  rtnval = new sdogeometry();&lt;br /&gt;  rtnval.LRS = _lrs;&lt;br /&gt;  rtnval.sdo_srid = _srid;&lt;br /&gt;  rtnval.Dimensionality = drawable.Dimensionality;&lt;br /&gt;  rtnval.ElemArray = tmp_elems;&lt;br /&gt;  rtnval.OrdinatesArray = tmp_ords;&lt;br /&gt;  rtnval.GeometryType = InferGeometryType(_drawables);&lt;br /&gt;  rtnval.PropertiesToGTYPE();&lt;br /&gt; }&lt;br /&gt; return rtnval;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-841361800841411966?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/841361800841411966/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2009/11/vi-new-sdogeometry-autodesk-map3d-2010.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/841361800841411966'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/841361800841411966'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2009/11/vi-new-sdogeometry-autodesk-map3d-2010.html' title='(VI) New SDO_GEOMETRY &lt;-&gt; Autodesk Map3d 2010'/><author><name>Dennis Jonio</name><uri>http://www.blogger.com/profile/14478827118325682041</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-5653040149484180380</id><published>2009-11-15T21:07:00.004+01:00</published><updated>2009-11-17T12:21:35.319+01:00</updated><title type='text'>(V) New SDO_GEOMETRY &lt;-&gt; Autodesk Map3d 2010</title><content type='html'>&lt;div&gt;Author: Jonio, Dennis&lt;/div&gt;&lt;br /&gt;As I stated in the last post:&lt;br /&gt;&lt;li&gt;Given a NetSdoGeometry.sdogeometry decompose it into a “DrawAble(s)”.&lt;br /&gt;As you would suspect this is mostly code. This is the actor that gets invoked every time DrawAbleSdoGeometry gets instantiated via DrawAbleSdoGeometry(sdogeometry aSDO_GEOMETRY) or the Geometry within an existing DrawAbleSdoGeometry gets changed.&lt;br /&gt;&lt;br /&gt;The todo here is to breakdown and pair SDO_ELEM_INFO elements with SDO_ORDINATES elements. The end result will be at least one DrawAble(s). &lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;private void DrawAblesFromGeometry()&lt;br /&gt;{&lt;br /&gt; sdogeometry g = Geometry;&lt;br /&gt; int[] elms = g.ElemArrayOfInts;&lt;br /&gt; decimal[] ords = g.OrdinatesArray;&lt;br /&gt; int dimensions = g.Dimensionality;&lt;br /&gt; int OFFSET = 0, nxtOFFSET = 0;&lt;br /&gt; int ETYPE = 0, nxtETYPE = 0;&lt;br /&gt; int INTERP = 0, nxtINTERP = 0;&lt;br /&gt; int ETYPE_plus_INTERP = 0;&lt;br /&gt; //Just to make it easier to work with&lt;br /&gt; List&lt;TriInts&gt; elmList = new List&lt;TriInts&gt;();&lt;br /&gt; for (int _i = 0; _i &lt; elms.Length; )&lt;br /&gt; {&lt;br /&gt;  TriInts tmp_triplet = new TriInts(elms[_i], elms[_i + 1], elms[_i + 2]);&lt;br /&gt;  elmList.Add(tmp_triplet);&lt;br /&gt;  _i = _i + 3;&lt;br /&gt; }&lt;br /&gt; //Iterate through the triplets&lt;br /&gt; for (int _j = 0; _j &lt; elmList.Count; )&lt;br /&gt; {&lt;br /&gt;  TriInts wrkrElm = elmList[_j];&lt;br /&gt;  OFFSET = wrkrElm.OFFSET;&lt;br /&gt;  ETYPE = wrkrElm.ETYPE;&lt;br /&gt;  INTERP = wrkrElm.INTERP;&lt;br /&gt;  ETYPE_plus_INTERP = ETYPE + INTERP;&lt;br /&gt;  //Look ahead is required for getting and setting offset into the ordinates array&lt;br /&gt;  if (_j &lt; elmList.Count - 1)&lt;br /&gt;  { nxtOFFSET = elmList[_j + 1].OFFSET; nxtETYPE = elmList[_j + 1].ETYPE; nxtINTERP = elmList[_j + 1].INTERP; }&lt;br /&gt;  else&lt;br /&gt;  { nxtOFFSET = nxtETYPE = nxtINTERP = 0; }&lt;br /&gt;  int len_of_ords = 0;&lt;br /&gt;  if (nxtOFFSET &gt; 0)&lt;br /&gt;  {&lt;br /&gt;   len_of_ords = nxtOFFSET - OFFSET; &lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;   len_of_ords = (ords.Length - OFFSET) + 1;&lt;br /&gt;  }&lt;br /&gt;  int len = 0;&lt;br /&gt;  //Based upon the ETYPE and the INTERPRETATION&lt;br /&gt;  switch (ETYPE)&lt;br /&gt;  {&lt;br /&gt;   case 1:&lt;br /&gt;    if (INTERP &gt; 1)&lt;br /&gt;    {&lt;br /&gt;     DrawAble drawp = new DrawAble(DrawAbleType.Point, dimensions);&lt;br /&gt;     DrawAbleSubComponent drawpc = new DrawAbleSubComponent();&lt;br /&gt;     drawpc.Etype = DrawAbleSubComponentEType.PointCluster;&lt;br /&gt;     drawpc.Elem = new int[] { 0, 1, INTERP };&lt;br /&gt;     drawpc.Ords = new decimal[len];&lt;br /&gt;     Array.Copy(ords, OFFSET - 1, drawpc.Ords, 0, len_of_ords);&lt;br /&gt;     drawp.SubComponents.Add(drawpc);&lt;br /&gt;     this.Drawables.Add(drawp);&lt;br /&gt;    }&lt;br /&gt;    else if (INTERP == 1)&lt;br /&gt;    {&lt;br /&gt;     DrawAble drawp1 = new DrawAble(DrawAbleType.Point, dimensions);&lt;br /&gt;     DrawAbleSubComponent drawp1c = new DrawAbleSubComponent();&lt;br /&gt;     drawp1c.Etype = DrawAbleSubComponentEType.Point;&lt;br /&gt;     drawp1c.Ords = new decimal[len_of_ords];&lt;br /&gt;     Array.Copy(ords, OFFSET - 1, drawp1c.Ords, 0, len_of_ords);&lt;br /&gt;     drawp1.SubComponents.Add(drawp1c);&lt;br /&gt;     this.Drawables.Add(drawp1);&lt;br /&gt;    }&lt;br /&gt;    break;&lt;br /&gt;   case 2:&lt;br /&gt;    DrawAble drawl = new DrawAble(DrawAbleType.Line, dimensions);&lt;br /&gt;    DrawAbleSubComponent drawlc = new DrawAbleSubComponent();&lt;br /&gt;    if (ETYPE_plus_INTERP == (int)DrawAbleSubComponentEType.SimpleLine)&lt;br /&gt;     drawlc.Etype = DrawAbleSubComponentEType.SimpleLine;&lt;br /&gt;    else&lt;br /&gt;     drawlc.Etype = DrawAbleSubComponentEType.SimpleLineAllCurves;&lt;br /&gt;    drawlc.Ords = new decimal[len_of_ords];&lt;br /&gt;    Array.Copy(ords, OFFSET - 1, drawlc.Ords, 0, len_of_ords);&lt;br /&gt;    drawl.SubComponents.Add(drawlc);&lt;br /&gt;    this.Drawables.Add(drawl);&lt;br /&gt;    break;&lt;br /&gt;    case 4:&lt;br /&gt;    DrawAble drawcombo = new DrawAble(DrawAbleType.Line, dimensions);&lt;br /&gt;    DrawAbleSubComponent drawcomboc = new DrawAbleSubComponent();&lt;br /&gt;    drawcomboc.Etype = DrawAbleSubComponentEType.CompoundLine;&lt;br /&gt;    int number_of_subelements = INTERP;&lt;br /&gt;    int final_len_of_elms = (number_of_subelements * 3) + 3;&lt;br /&gt;    int first_OFFSET = OFFSET;&lt;br /&gt;    //The subelements PLUS the header&lt;br /&gt;    int[] redone_elms = new int[final_len_of_elms];&lt;br /&gt;    int redone_n = 0;&lt;br /&gt;    redone_elms[redone_n++] = OFFSET - first_OFFSET;&lt;br /&gt;    redone_elms[redone_n++] = ETYPE;&lt;br /&gt;    redone_elms[redone_n++] = INTERP;&lt;br /&gt;    _j = _j + 1;&lt;br /&gt;    for (int k = 1; k &lt;= number_of_subelements; )&lt;br /&gt;    {&lt;br /&gt;     OFFSET = elmList[_j].OFFSET;&lt;br /&gt;     ETYPE = elmList[_j].ETYPE;&lt;br /&gt;     INTERP = elmList[_j].INTERP;&lt;br /&gt;&lt;br /&gt;     redone_elms[redone_n + 0] = OFFSET - first_OFFSET;&lt;br /&gt;     redone_elms[redone_n + 1] = ETYPE;&lt;br /&gt;     redone_elms[redone_n + 2] = INTERP;&lt;br /&gt;     redone_n = redone_n + 3;&lt;br /&gt;     k = k + 1;&lt;br /&gt;     _j = _j + 1;&lt;br /&gt;    }&lt;br /&gt;    // _j is now pointing past this "4" string and we MAY be looking at another drawable&lt;br /&gt;    // We find out by comparing the redone_elms count w/elmList count.&lt;br /&gt;    if ((number_of_subelements + 1) &lt; elmList.Count)&lt;br /&gt;    {&lt;br /&gt;     len_of_ords = elmList[_j].OFFSET - first_OFFSET;&lt;br /&gt;     //We now decrement _j because we did not consume the entire thing.&lt;br /&gt;     _j = _j - 1;&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;     len_of_ords = (ords.Length - first_OFFSET) + 1;&lt;br /&gt;&lt;br /&gt;    drawcomboc.Ords = new decimal[len_of_ords];&lt;br /&gt;    Array.Copy(ords, first_OFFSET - 1, drawcomboc.Ords, 0, len_of_ords);&lt;br /&gt;    //Copy the elms&lt;br /&gt;    drawcomboc.Elem = new int[(number_of_subelements * 3) + 3];&lt;br /&gt;    Array.Copy(redone_elms, 0, drawcomboc.Elem, 0, (number_of_subelements * 3) + 3);&lt;br /&gt;    //Add the component to the drawable&lt;br /&gt;    drawcombo.SubComponents.Add(drawcomboc);&lt;br /&gt;    //Add the drawable&lt;br /&gt;    this.Drawables.Add(drawcombo);&lt;br /&gt;    break;&lt;br /&gt;    case 1003:&lt;br /&gt;    DrawAble drawsurf1003 = new DrawAble(DrawAbleType.Surface, dimensions);&lt;br /&gt;    DrawAbleSubComponent drawsurfc1003 = new DrawAbleSubComponent();&lt;br /&gt;    switch (ETYPE_plus_INTERP)&lt;br /&gt;    {&lt;br /&gt;     case (int)DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine:&lt;br /&gt;      drawsurfc1003.Etype = DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine;&lt;br /&gt;      break;&lt;br /&gt;     case (int)DrawAbleSubComponentEType.SimpleSurfaceOuterRingCircle:&lt;br /&gt;      drawsurfc1003.Etype = DrawAbleSubComponentEType.SimpleSurfaceOuterRingCircle;&lt;br /&gt;      break;&lt;br /&gt;     case (int)DrawAbleSubComponentEType.SimpleSurfaceOuterRingAllCurves:&lt;br /&gt;      drawsurfc1003.Etype = DrawAbleSubComponentEType.SimpleSurfaceOuterRingAllCurves;&lt;br /&gt;      break;&lt;br /&gt;     case (int)DrawAbleSubComponentEType.SimpleSurfaceOuterRingRectangle:&lt;br /&gt;      drawsurfc1003.Etype = DrawAbleSubComponentEType.SimpleSurfaceOuterRingRectangle;&lt;br /&gt;      break;&lt;br /&gt;     default:&lt;br /&gt;      break;&lt;br /&gt;    }&lt;br /&gt;    if (nxtOFFSET == 0)&lt;br /&gt;     len = ords.Length - OFFSET + 1;&lt;br /&gt;    else&lt;br /&gt;     len = Math.Abs(nxtOFFSET - OFFSET);&lt;br /&gt;    drawsurfc1003.Ords = new decimal[len];&lt;br /&gt;    Array.Copy(ords, OFFSET - 1, drawsurfc1003.Ords, 0, len_of_ords);&lt;br /&gt;    drawsurf1003.SubComponents.Add(drawsurfc1003);&lt;br /&gt;    this.Drawables.Add(drawsurf1003);&lt;br /&gt;    break;&lt;br /&gt;    case 2003:&lt;br /&gt;    DrawAbleSubComponent drawsurfc2003 = new DrawAbleSubComponent();&lt;br /&gt;    switch (ETYPE_plus_INTERP)&lt;br /&gt;    {&lt;br /&gt;     case (int)DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine:&lt;br /&gt;      drawsurfc2003.Etype = DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine;&lt;br /&gt;      break;&lt;br /&gt;     case (int)DrawAbleSubComponentEType.SimpleSurfaceInnerRingCircle:&lt;br /&gt;      drawsurfc2003.Etype = DrawAbleSubComponentEType.SimpleSurfaceInnerRingCircle;&lt;br /&gt;      break;&lt;br /&gt;     case (int)DrawAbleSubComponentEType.SimpleSurfaceInnerRingAllCurves:&lt;br /&gt;      drawsurfc2003.Etype = DrawAbleSubComponentEType.SimpleSurfaceInnerRingAllCurves;&lt;br /&gt;      break;&lt;br /&gt;     case (int)DrawAbleSubComponentEType.SimpleSurfaceInnerRingRectangle:&lt;br /&gt;      drawsurfc2003.Etype = DrawAbleSubComponentEType.SimpleSurfaceInnerRingRectangle;&lt;br /&gt;      break;&lt;br /&gt;     default:&lt;br /&gt;      break;&lt;br /&gt;    }&lt;br /&gt;    if (nxtOFFSET == 0)&lt;br /&gt;     len = ords.Length - OFFSET + 1;&lt;br /&gt;    else&lt;br /&gt;     len = Math.Abs(nxtOFFSET - OFFSET);&lt;br /&gt;    drawsurfc2003.Ords = new decimal[len];&lt;br /&gt;    Array.Copy(ords, OFFSET - 1, drawsurfc2003.Ords, 0, len_of_ords);&lt;br /&gt;    bool hasHome = false;&lt;br /&gt;    for (int _i = this.Drawables.Count - 1; _i &gt;= 0; _i--)&lt;br /&gt;    {&lt;br /&gt;     if (Drawables[_i].DrawEtype == DrawAbleType.Surface)&lt;br /&gt;     {&lt;br /&gt;      Drawables[_i].SubComponents.Add(drawsurfc2003);&lt;br /&gt;      hasHome = true;&lt;br /&gt;      break;&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;    if (hasHome == false)&lt;br /&gt;     OrphanComponents.Add(drawsurfc2003);&lt;br /&gt;    break;&lt;br /&gt;    case 1005:&lt;br /&gt;    case 2005:&lt;br /&gt;    DrawAble drawsurfX005 = new DrawAble(DrawAbleType.Surface, dimensions);                        &lt;br /&gt;    DrawAbleSubComponent drawsurfcX005 = new DrawAbleSubComponent();&lt;br /&gt;    if (ETYPE == 1005)&lt;br /&gt;     drawsurfcX005.Etype = DrawAbleSubComponentEType.CompoundSurfaceOuterRingLine;&lt;br /&gt;    else&lt;br /&gt;     drawsurfcX005.Etype = DrawAbleSubComponentEType.CompoundSurfaceInnerRingLine;&lt;br /&gt;    number_of_subelements = INTERP;&lt;br /&gt;    final_len_of_elms = (number_of_subelements * 3) + 3;&lt;br /&gt;    first_OFFSET = OFFSET;&lt;br /&gt;    //The subelements PLUS the header&lt;br /&gt;    redone_elms = new int[final_len_of_elms];&lt;br /&gt;    redone_n = 0;&lt;br /&gt;    redone_elms[redone_n++] = OFFSET - first_OFFSET;&lt;br /&gt;    redone_elms[redone_n++] = ETYPE;&lt;br /&gt;    redone_elms[redone_n++] = INTERP;&lt;br /&gt;    _j = _j + 1;&lt;br /&gt;    for (int k = 1; k &lt;= number_of_subelements; )&lt;br /&gt;    {&lt;br /&gt;     OFFSET = elmList[_j].OFFSET;&lt;br /&gt;     ETYPE = elmList[_j].ETYPE;&lt;br /&gt;     INTERP = elmList[_j].INTERP;&lt;br /&gt;&lt;br /&gt;     redone_elms[redone_n + 0] = OFFSET - first_OFFSET;&lt;br /&gt;     redone_elms[redone_n + 1] = ETYPE;&lt;br /&gt;     redone_elms[redone_n + 2] = INTERP;&lt;br /&gt;     redone_n = redone_n + 3;&lt;br /&gt;     k = k + 1;&lt;br /&gt;     _j = _j + 1;&lt;br /&gt;    }&lt;br /&gt;    //We must remember to decrement _j because we may not have consumed the entire thing.&lt;br /&gt;    if ((number_of_subelements + 1) &lt; elmList.Count)&lt;br /&gt;    {&lt;br /&gt;     len_of_ords = elmList[_j].OFFSET - first_OFFSET;&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;     len_of_ords = (ords.Length - first_OFFSET) + 1;&lt;br /&gt;&lt;br /&gt;    drawsurfcX005.Ords = new decimal[len_of_ords];&lt;br /&gt;    Array.Copy(ords, first_OFFSET - 1, drawsurfcX005.Ords, 0, len_of_ords);&lt;br /&gt;    //Copy the elms&lt;br /&gt;    drawsurfcX005.Elem = new int[(number_of_subelements * 3) + 3];&lt;br /&gt;    Array.Copy(redone_elms, 0, drawsurfcX005.Elem, 0, (number_of_subelements * 3) + 3);&lt;br /&gt;    //Add the drawable if it is a 1005&lt;br /&gt;    if (drawsurfcX005.Etype == DrawAbleSubComponentEType.CompoundSurfaceOuterRingLine)&lt;br /&gt;    {&lt;br /&gt;     //Add the component to the drawable&lt;br /&gt;     drawsurfX005.SubComponents.Add(drawsurfcX005);&lt;br /&gt;     this.Drawables.Add(drawsurfX005);&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;     // This is a 2005 and it needs the "nearest" outer ring to live within&lt;br /&gt;     hasHome = false;&lt;br /&gt;     for (int _i = this.Drawables.Count - 1; _i &gt;= 0; _i--)&lt;br /&gt;     {&lt;br /&gt;      if (Drawables[_i].DrawEtype == DrawAbleType.Surface)&lt;br /&gt;      {&lt;br /&gt;       Drawables[_i].SubComponents.Add(drawsurfcX005);&lt;br /&gt;       hasHome = true;&lt;br /&gt;       break;&lt;br /&gt;      }&lt;br /&gt;     }&lt;br /&gt;     if (hasHome == false)&lt;br /&gt;      OrphanComponents.Add(drawsurfcX005);&lt;br /&gt;    }&lt;br /&gt;    //We moved _j ahead ONE(1) to far ... in persuit of the nxtOFFSET.&lt;br /&gt;    //We must decrement it so we land back at real next "header" triplet&lt;br /&gt;    _j = _j - 1;&lt;br /&gt;    break;&lt;br /&gt;   default:&lt;br /&gt;    break;&lt;br /&gt;  }&lt;br /&gt;  _j = _j + 1;&lt;br /&gt; }// main for loop&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-5653040149484180380?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/5653040149484180380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2009/11/v-new-sdogeometry-autodesk-map3d-2010.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/5653040149484180380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/5653040149484180380'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2009/11/v-new-sdogeometry-autodesk-map3d-2010.html' title='(V) New SDO_GEOMETRY &lt;-&gt; Autodesk Map3d 2010'/><author><name>Dennis Jonio</name><uri>http://www.blogger.com/profile/14478827118325682041</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-8415873683916110886</id><published>2009-11-13T21:18:00.007+01:00</published><updated>2009-11-15T21:07:15.154+01:00</updated><title type='text'>(IV) New SDO_GEOMETRY &lt;-&gt; Autodesk Map3d 2010</title><content type='html'>&lt;div&gt;Author: Jonio, Dennis&lt;/div&gt;&lt;br /&gt;Before I begin to discuss additional detail I will briefly illustrate what it looks like to materialize an Autodesk/Map3d object from a NetSdoGeometry.sdogeometry with this approach. The other class &lt;strong&gt;DrawAbleDwg&lt;/strong&gt; shown below has not been discussed at all to this point. This is in fact the simplest pattern that can be used when dealing with the MULTI type. &lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;using MDADDrawAbles;&lt;br /&gt;using MDADDrawAbleDwg;&lt;br /&gt;using DDwg = MDADDrawAbleDwg.DrawAbleDwg;&lt;br /&gt;&lt;br /&gt;DrawAbleSdoGeometry D_sdo = new DrawAbleSdoGeometry(some_sdogeometry);&lt;br /&gt;foreach (DrawAble d in D_sdo.Drawables)&lt;br /&gt;{&lt;br /&gt;      object aObj = DDwg.DrawAbleDwgObj(d);&lt;br /&gt;&lt;br /&gt;      if (aObj is Autodesk.AutoCAD.DatabaseServices.MPolygon)&lt;br /&gt;      {&lt;br /&gt;          DDwg.AddMPolygon(aObj as MPolygon, 5, "MPolygon", "a polygon");&lt;br /&gt;      }&lt;br /&gt;      else if (aObj is Autodesk.AutoCAD.DatabaseServices.Polyline)&lt;br /&gt;          {&lt;br /&gt;             DDwg.AddPline(aObj as Polyline, 6, "Polyline", "a polyline");&lt;br /&gt;           }&lt;br /&gt;           else if (aObj is Autodesk.AutoCAD.DatabaseServices.DBPoint)&lt;br /&gt;                {&lt;br /&gt;                  DDwg.AddPointd(aObj as DBPoint, 4, "Point", "a point");                             &lt;br /&gt;                }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The following illustrates just the opposite, a NetSdoGeometry.sdogeometry from multiple Autodesk/Map3d objects. The three(3) in this case will capture the Z axis. Actually I don't know what I am going to do with it but I have it if it is necessary.  &lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;DrawAble d3 = null;&lt;br /&gt;PromptSelectionOptions pso = new PromptSelectionOptions();&lt;br /&gt;pso.MessageForAdding = "\nEntities must be MPolygons, Polylines, Arc, Circles or Points.";&lt;br /&gt;pso.AllowDuplicates = false;&lt;br /&gt;pso.AllowSubSelections = false;&lt;br /&gt;pso.SingleOnly = false;&lt;br /&gt;&lt;br /&gt;PromptSelectionResult psr = ed.GetSelection(pso, MakeFilter());&lt;br /&gt;if (psr.Status == PromptStatus.OK)&lt;br /&gt;{&lt;br /&gt; List&lt;DrawAble&gt; drawList = new List&lt;DrawAble&gt;();&lt;br /&gt;&lt;br /&gt; using (Transaction tr = db.TransactionManager.StartTransaction())&lt;br /&gt; {&lt;br /&gt;  foreach (SelectedObject seleobj in psr.Value)&lt;br /&gt;  {&lt;br /&gt;   Entity ent;&lt;br /&gt;   Entity entdb = (Entity)tr.GetObject(seleobj.ObjectId, OpenMode.ForRead);&lt;br /&gt;   //Other stuff&lt;br /&gt;   ent = entdb;&lt;br /&gt;   Polyline pl = ent as Polyline;&lt;br /&gt;   Polyline2d pl2d = ent as Polyline2d;&lt;br /&gt;   Polyline3d pl3d = ent as Polyline3d;&lt;br /&gt;   Arc anArc = ent as Arc;&lt;br /&gt;   DBPoint dbPoint = ent as DBPoint;&lt;br /&gt;   MPolygon mpoly = ent as MPolygon;&lt;br /&gt;   Line line = ent as Line;&lt;br /&gt;   Circle circ = ent as Circle;&lt;br /&gt;   if (line == null &amp;&amp; pl == null &amp;&amp; pl2d == null &amp;&amp; pl3d == null &amp;&amp; anArc == null&lt;br /&gt;    &amp;&amp; dbPoint == null &amp;&amp; mpoly == null &amp;&amp; circ == null)&lt;br /&gt;   {&lt;br /&gt;   }&lt;br /&gt;   else&lt;br /&gt;   {&lt;br /&gt;&lt;br /&gt;    if (pl != null)&lt;br /&gt;    {&lt;br /&gt;     d3 = DDwg.LineCurveDrawAbleFromPolyline(pl, null, null, 3);&lt;br /&gt;    }&lt;br /&gt;    if (pl2d != null)&lt;br /&gt;    {&lt;br /&gt;     d3 = DDwg.LineCurveDrawAbleFromPolyline(null, pl2d, null, 3);&lt;br /&gt;    }&lt;br /&gt;    if (pl3d != null)&lt;br /&gt;    {&lt;br /&gt;     d3 = DDwg.LineCurveDrawAbleFromPolyline(null, null, pl3d, 3);&lt;br /&gt;    }&lt;br /&gt;    if (mpoly != null)&lt;br /&gt;    {&lt;br /&gt;     d3 = DDwg.PolygonDrawAbleFromMPolygon(mpoly, 3);&lt;br /&gt;    }&lt;br /&gt;    if (anArc != null)&lt;br /&gt;    {&lt;br /&gt;     d3 = DDwg.LineCurveDrawAbleFromArc(anArc, 3);&lt;br /&gt;    }&lt;br /&gt;    if (line != null)&lt;br /&gt;    {&lt;br /&gt;     d3 = DDwg.LineCurveDrawAbleFromLine(line, 3);&lt;br /&gt;    }&lt;br /&gt;    if (dbPoint != null)&lt;br /&gt;    {&lt;br /&gt;     d3 = DDwg.PointDrawAbleFromPoint(dbPoint, 3);&lt;br /&gt;    }&lt;br /&gt;    if (circ != null)&lt;br /&gt;    {&lt;br /&gt;     d3 = DDwg.LineCurveDrawAbleFromCircle(circ, 3);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;   drawList.Add(d3);&lt;br /&gt;  }//foreach object in the selection set&lt;br /&gt; }//using transaction&lt;br /&gt;&lt;br /&gt; sdogeometry geometry = DrawAbleSdoGeometryUtil.SdoGeometryFromDrawAble(drawList, 0, 2236);&lt;br /&gt;&lt;br /&gt;}//prompt stat OK &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;DrawAbleSdoGeometryUtil.SdoGeometryFromDrawAble(drawList, 0, 2236); Passing in the DrawAble, the LRS, and the SRID produces a sdogeometry!&lt;br /&gt;&lt;br /&gt;Here is the list of things that remain to be shown:&lt;br /&gt; &lt;li&gt;Given a NetSdoGeometry.sdogeometry decompose it into a “DrawAble(s)”.&lt;br /&gt; &lt;li&gt;Given some “DrawAble(s)” compose a NetSdoGeometry.sdogeometry.&lt;br /&gt; &lt;li&gt;Given one or more Autodesk/Map3d objects decompose it(them) into “Drawable(s)”.&lt;br /&gt; &lt;li&gt;Given a “DrawAble” compose a Autodesk/Map3d object.&lt;br /&gt;To be continued ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-8415873683916110886?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/8415873683916110886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2009/11/iv-new-sdogeometry-autodesk-map3d-2010.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/8415873683916110886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/8415873683916110886'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2009/11/iv-new-sdogeometry-autodesk-map3d-2010.html' title='(IV) New SDO_GEOMETRY &lt;-&gt; Autodesk Map3d 2010'/><author><name>Dennis Jonio</name><uri>http://www.blogger.com/profile/14478827118325682041</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-4152399679751292809</id><published>2009-11-12T16:33:00.002+01:00</published><updated>2009-11-12T17:14:43.665+01:00</updated><title type='text'>(III) New SDO_GEOMETRY &lt;-&gt; Autodesk Map3d 2010</title><content type='html'>&lt;div&gt;Author: Jonio, Dennis&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Before I forget I did put together a simple class to aid in manipulating the three(3) element array structures that comprise SDO_ELEM_INFO_ARRAY.&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;    [Serializable]&lt;br /&gt;    public class TriInts&lt;br /&gt;    {&lt;br /&gt;        public int OFFSET&lt;br /&gt;        { set { TriInt[0] = value; } get { return TriInt[0]; } }&lt;br /&gt;        public int ETYPE&lt;br /&gt;        { set { TriInt[1] = value; } get { return TriInt[1]; } }&lt;br /&gt;        public int INTERP&lt;br /&gt;        { set { TriInt[2] = value; } get { return TriInt[2]; } }&lt;br /&gt;        private int[] TriInt;&lt;br /&gt;&lt;br /&gt;        public TriInts()&lt;br /&gt;        {&lt;br /&gt;            TriInt = new int[] { 0, 0, 0 };&lt;br /&gt;        }&lt;br /&gt;        public TriInts(int o, int e, int i)&lt;br /&gt;        {&lt;br /&gt;            TriInt = new int[3];&lt;br /&gt;            TriInt[0] = o;&lt;br /&gt;            TriInt[1] = e;&lt;br /&gt;            TriInt[2] = i;&lt;br /&gt;        }&lt;br /&gt;        public TriInts(TriInts triint)&lt;br /&gt;        {&lt;br /&gt;            TriInt = new int[3];&lt;br /&gt;            TriInt[0] = triint.OFFSET;&lt;br /&gt;            TriInt[1] = triint.ETYPE;&lt;br /&gt;            TriInt[2] = triint.INTERP;&lt;br /&gt;        }&lt;br /&gt;        public int[] ToArray()&lt;br /&gt;        {&lt;br /&gt;            return new int[] { OFFSET, ETYPE, INTERP };&lt;br /&gt;        }&lt;br /&gt;    }//eoc TriInts&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So now we get to the primary actor &lt;strong&gt;DrawAbleSdoGeometry&lt;/strong&gt;. The container class for the NetSdoGeometry.sdogeometry type and the supporting cast of players to break sdogeometry down into DrawAble(s) and build a sdogeometry from DrawAble(s).  Again the paradigm is all about this intermediate drawable construct so Autodesk/Map3d doesn’t come into play here. That is all handled in a separate class!&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;    [Serializable]&lt;br /&gt;    public class DrawAbleSdoGeometry&lt;br /&gt;    {&lt;br /&gt;        private sdogeometry m_Geometry;&lt;br /&gt;        public const decimal DefaultSRID2236 = 2236;&lt;br /&gt;        public const int DefaultLRS0 = 0;&lt;br /&gt;        public const int DefaultDimensionality2D = 2;&lt;br /&gt;        public const int DefaultDimensionality3D = 3;&lt;br /&gt;        public decimal SRID = DefaultSRID2236;&lt;br /&gt;        public int LRS = DefaultLRS0;&lt;br /&gt;        public int Dimensionality = DefaultDimensionality2D;&lt;br /&gt;        public List&lt;DrawAble&gt; Drawables = new List&lt;DrawAble&gt;();&lt;br /&gt;        public List&lt;DrawAbleSubComponent&gt; OrphanComponents = new List&lt;DrawAbleSubComponent&gt;();        &lt;br /&gt;        // Default ctor - nothing to do&lt;br /&gt;        public DrawAbleSdoGeometry() { }&lt;br /&gt;        // ctor from an existing SDO_GEOMETRY object&lt;br /&gt;        public DrawAbleSdoGeometry(sdogeometry aGeometry)&lt;br /&gt;        {&lt;br /&gt;            this.Geometry = aGeometry;&lt;br /&gt;        }&lt;br /&gt;}//eoc DrawAbleSdoGeometry&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I set a default Dimensionality, LRS and SRID but have left them totally accessible. I am not one to hide things away in some private corner somewhere unless it just is nonsensical to do otherwise. Like DrawAblesFromGeometry(), the player that decomposes a sdogeometry/SDO_GEOMETRY object into DrawAble(s). It only made sense to me to invoke this directly from the “setter” for the class’ Geometry object.&lt;br /&gt;Note also that within the “setter” I deal with that Optimized Point issue.&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;       public sdogeometry Geometry&lt;br /&gt;        {&lt;br /&gt;            get { return this.m_Geometry; }&lt;br /&gt;&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                m_Geometry = value;&lt;br /&gt;                try&lt;br /&gt;                {&lt;br /&gt;                    m_Geometry.PropertiesFromGTYPE();&lt;br /&gt;                    Dimensionality = m_Geometry.Dimensionality;&lt;br /&gt;&lt;br /&gt;                    if (m_Geometry.sdo_point != null)&lt;br /&gt;                    {&lt;br /&gt;                        m_Geometry.ElemArray = new decimal[] { 1, 1, 1 };&lt;br /&gt;                        if (m_Geometry.Dimensionality == 2)&lt;br /&gt;                            m_Geometry.OrdinatesArray = new decimal[] { (decimal)m_Geometry.sdo_point.X, (decimal)m_Geometry.sdo_point.Y };&lt;br /&gt;                        else if (m_Geometry.Dimensionality == 3)&lt;br /&gt;                            m_Geometry.OrdinatesArray = new decimal[] { (decimal)m_Geometry.sdo_point.X, (decimal)m_Geometry.sdo_point.Y, (decimal)m_Geometry.sdo_point.Z };&lt;br /&gt;                        m_Geometry.sdo_point = null;&lt;br /&gt;                    }&lt;br /&gt;                    if (m_Geometry.ElemArray != null &amp;&amp; m_Geometry.OrdinatesArray != null)&lt;br /&gt;                        DrawAblesFromGeometry();&lt;br /&gt;                }&lt;br /&gt;                catch (System.Exception) {/*Just eat it all*/}&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As regards catching and eating any errors at this level I am ambivilant. I really do assume VALID geometry coming in because I produce VALID geometry on the other end. You may see it differently.&lt;/div&gt;&lt;br /&gt;To be continued …&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-4152399679751292809?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/4152399679751292809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2009/11/iii-new-sdogeometry-autodesk-map3d-2010.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/4152399679751292809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/4152399679751292809'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2009/11/iii-new-sdogeometry-autodesk-map3d-2010.html' title='(III) New SDO_GEOMETRY &lt;-&gt; Autodesk Map3d 2010'/><author><name>Dennis Jonio</name><uri>http://www.blogger.com/profile/14478827118325682041</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-6911328563579486239</id><published>2009-11-12T12:27:00.007+01:00</published><updated>2009-11-12T13:30:20.278+01:00</updated><title type='text'>(II) New SDO_GEOMETRY &lt;-&gt; Autodesk Map3d 2010</title><content type='html'>&lt;div&gt;Author: Jonio, Dennis&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;p&gt;The DrawAbleType enums were easy. I just had to give them values that could be distinguised via “OR”ing them together.&lt;br /&gt;&lt;li&gt;Point = 1,&lt;br /&gt;&lt;li&gt;Line = 2,&lt;br /&gt;&lt;li&gt;Surface = 4&lt;/p&gt;&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;       public static int InferGeometryType(List&lt;DrawAble&gt; _drawables)&lt;br /&gt;        {&lt;br /&gt;            int rtnval = 0;&lt;br /&gt;            if (_drawables.Count == 1)&lt;br /&gt;            {&lt;br /&gt;                switch (_drawables[0].DrawEtype)&lt;br /&gt;                {&lt;br /&gt;                    case DrawAbleType.Point:&lt;br /&gt;                        rtnval = 1;&lt;br /&gt;                        break;&lt;br /&gt;                    case DrawAbleType.Line:&lt;br /&gt;                        rtnval = 2;&lt;br /&gt;                        break;&lt;br /&gt;                    case DrawAbleType.Surface:&lt;br /&gt;                        rtnval = 3;&lt;br /&gt;                        break;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                int ttype = 0;&lt;br /&gt;                foreach (DrawAble d in _drawables)&lt;br /&gt;                    ttype = ttype | (int)d.DrawEtype;&lt;br /&gt;&lt;br /&gt;                switch (ttype)&lt;br /&gt;                {&lt;br /&gt;                    case 1:&lt;br /&gt;                        rtnval = 5; //MultiPoint&lt;br /&gt;                        break;&lt;br /&gt;                    case 2:&lt;br /&gt;                        rtnval = 6; //MultiLine&lt;br /&gt;                        break;&lt;br /&gt;                    case 4:&lt;br /&gt;                        rtnval = 7; //MultiPolygon&lt;br /&gt;                        break;&lt;br /&gt;                    default:&lt;br /&gt;                        rtnval = 4; //Collection&lt;br /&gt;                        break;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            return rtnval;&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;I really wrestled with these DrawAbleSubComponentEType enums. I tried to be really clever with these values and somehow take advantage of the relationship between ETYPE and INTERPRETATION. &lt;strong&gt;Tried&lt;/strong&gt; is the operative word. &lt;br /&gt;&lt;li&gt;Point = 1,                              //1&lt;br /&gt;&lt;li&gt;PointCluster = 10,                      //1 + n&lt;br /&gt;&lt;li&gt;PointOriented = 19,                     //Not supported OrientedPoint&lt;br /&gt;&lt;li&gt;SimpleLine = 3,                         //2 + 1&lt;br /&gt;&lt;li&gt;SimpleLineAllCurves = 4,                //2 + 2&lt;br /&gt;&lt;li&gt;CompoundLine = 40,                      //4 + n&lt;br /&gt;&lt;li&gt;SimpleSurfaceOuterRingLine = 1004,      //1003 + 1&lt;br /&gt;&lt;li&gt;SimpleSurfaceOuterRingAllCurves = 1005, //1003 + 2&lt;br /&gt;&lt;li&gt;SimpleSurfaceOuterRingRectangle = 1006, //1003 + 3&lt;br /&gt;&lt;li&gt;SimpleSurfaceOuterRingCircle = 1007,    //1003 + 4&lt;br /&gt;&lt;li&gt;SimpleSurfaceInnerRingLine = 2004,      //2003 + 1&lt;br /&gt;&lt;li&gt;SimpleSurfaceInnerRingAllCurves = 2005, //2003 + 2&lt;br /&gt;&lt;li&gt;SimpleSurfaceInnerRingRectangle = 2006, //2003 + 3&lt;br /&gt;&lt;li&gt;SimpleSurfaceInnerRingCircle = 2007,    //2003 + 4&lt;br /&gt;&lt;li&gt;CompoundSurfaceOuterRingLine = 10050,   //1005 + n&lt;br /&gt;&lt;li&gt;CompoundSurfaceInnerRingLine = 20050    //2005 + n&lt;br /&gt;The specification has to many exceptions for this to work but at least I have my unique values.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I do wonder &lt;strong&gt;alot&lt;/strong&gt; as to why Oracle set up the unique combinations for Circle, Rectangle and instances of all Curves. I did read the spec on “Oriented Point” and just arbitrarily decided NOT to support it. I will never use it and I guess I am the boss. So if you need that you will have to do it yourself. It should be a straight forward job for someone with the motivation.&lt;/P&gt;&lt;br /&gt;When it gets time to resolve these into the “real” ETYPE and INTERPRETATION values I just set up a couple static methods in a static utility class.&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;        public static int BasicETYPE(DrawAbleSubComponentEType t)&lt;br /&gt;        {&lt;br /&gt;            int rtnval = 0;&lt;br /&gt;            switch (t)&lt;br /&gt;            {&lt;br /&gt;                case DrawAbleSubComponentEType.Point:&lt;br /&gt;                case DrawAbleSubComponentEType.PointCluster:&lt;br /&gt;                case DrawAbleSubComponentEType.PointOriented:&lt;br /&gt;                    rtnval = 1;&lt;br /&gt;                    break;&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleLine:&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleLineAllCurves:&lt;br /&gt;                    rtnval = 2;&lt;br /&gt;                    break;&lt;br /&gt;                case DrawAbleSubComponentEType.CompoundLine:&lt;br /&gt;                    rtnval = 4;&lt;br /&gt;                    break;&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine:&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceOuterRingAllCurves:&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceOuterRingCircle:&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceOuterRingRectangle:&lt;br /&gt;                    rtnval = 1003;&lt;br /&gt;                    break;&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine:&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceInnerRingAllCurves:&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceInnerRingCircle:&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceInnerRingRectangle:&lt;br /&gt;                    rtnval = 2003;&lt;br /&gt;                    break;&lt;br /&gt;                case DrawAbleSubComponentEType.CompoundSurfaceOuterRingLine:&lt;br /&gt;                    rtnval = 1005;&lt;br /&gt;                    break;&lt;br /&gt;                case DrawAbleSubComponentEType.CompoundSurfaceInnerRingLine:&lt;br /&gt;                    rtnval = 2005;&lt;br /&gt;                    break;&lt;br /&gt;                default:&lt;br /&gt;                    break;&lt;br /&gt;            }&lt;br /&gt;            return rtnval;&lt;br /&gt;        }&lt;br /&gt;       public static int BasicINTERPRETATION(DrawAbleSubComponentEType t)&lt;br /&gt;        {&lt;br /&gt;            int rtnval = 0;&lt;br /&gt;            switch (t)&lt;br /&gt;            {&lt;br /&gt;                case DrawAbleSubComponentEType.Point:&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleLine:&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine:&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine:&lt;br /&gt;                    rtnval = 1;&lt;br /&gt;                    break;&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceInnerRingAllCurves:&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceOuterRingAllCurves:&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleLineAllCurves:&lt;br /&gt;                    rtnval = 2;&lt;br /&gt;                    break;&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceOuterRingRectangle:&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceInnerRingRectangle:&lt;br /&gt;                    rtnval = 3;&lt;br /&gt;                    break;&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceInnerRingCircle:&lt;br /&gt;                case DrawAbleSubComponentEType.SimpleSurfaceOuterRingCircle:&lt;br /&gt;                    rtnval = 4;&lt;br /&gt;                    break;&lt;br /&gt;                case DrawAbleSubComponentEType.PointCluster:&lt;br /&gt;                case DrawAbleSubComponentEType.CompoundLine:&lt;br /&gt;                case DrawAbleSubComponentEType.CompoundSurfaceOuterRingLine:&lt;br /&gt;                case DrawAbleSubComponentEType.CompoundSurfaceInnerRingLine:&lt;br /&gt;                    rtnval = 0;&lt;br /&gt;                    break;&lt;br /&gt;                case DrawAbleSubComponentEType.PointOriented:&lt;br /&gt;                    rtnval = 9;&lt;br /&gt;                    break;&lt;br /&gt;                default:&lt;br /&gt;                    break;&lt;br /&gt;            }&lt;br /&gt;            return rtnval;&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To be continued ...&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-6911328563579486239?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/6911328563579486239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2009/11/ii-new-sdogeometry-autodesk-map3d-2010.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/6911328563579486239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/6911328563579486239'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2009/11/ii-new-sdogeometry-autodesk-map3d-2010.html' title='(II) New SDO_GEOMETRY &lt;-&gt; Autodesk Map3d 2010'/><author><name>Dennis Jonio</name><uri>http://www.blogger.com/profile/14478827118325682041</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-6220803805093138150</id><published>2009-11-09T13:19:00.010+01:00</published><updated>2009-11-12T11:50:54.483+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sdo_geomerty'/><title type='text'>(I) New SDO_GEOMETRY &lt;-&gt; Autodesk Map3d 2010</title><content type='html'>&lt;div&gt;Author: Jonio, Dennis&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;Howdy all.&lt;br /&gt;Well, it has really been awhile since that last post. By the way, I have no idea what happened to Maksim Sestic. Anyone willing to let me know? &lt;br /&gt;&lt;br /&gt;Anyway a lot has transpired over the months not the least of which is that some time ago I built a shiny new Autodesk 2010/Map3d &lt;-&gt; SDO_GEOMETRY translator. &lt;br /&gt;&lt;br /&gt;The learning example I have posted here was/is OK and served its purpose. However, like most software it had to be fixed and/or enhanced (and in this case just thrown away!)&lt;br /&gt;The new converter supports everything that is in keeping with the Oracle Locator’s - Right To Use license. Obviously then there is no 3D object support. Curves are still fully supported and now ALL of the MULT types are supported. I do include support for the Z axis in this generation. In order to support the MULTI types I forced myself into building some “intermediate” objects. This also lays some of the groundwork for a different geometry object generator in the future. No, we are not having any problems or issues with Autodesk but maybe something else will come along. My NetSdoGeometry.sdogeometry object had to be tweaked a little so that it fully supported the Z axis. Beyond that it is good to go.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;     Three(3) primary objectives drove this iteration of the translator.&lt;br /&gt;      I) I wished to support a Z axis value&lt;br /&gt;      II) I wished to support the Oracle MULTI types&lt;br /&gt;      III) A more flexible overall design in general.&lt;br /&gt;I had to modify my sdogeometry &lt;strong&gt;AsText&lt;/strong&gt; property/ToString method to support the Z axis. If you recall I go out of my way to NOT utilize the "optimized point". I am sure it is a fine thing. For me, logically and programmatically, it is more trouble than its worth. In my way of thinking there is nothing wrong with an SDO_ELEM_INFO_ARRAY(1,1,1) and it is somewhat more  consistent with the rest of the standard. I do of course read them in but I never output a SDO_POINT.&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;   public string AsText&lt;br /&gt; {&lt;br /&gt;  get&lt;br /&gt;  {&lt;br /&gt;   StringBuilder sb = new StringBuilder();&lt;br /&gt;   sb.Append("MDSYS.SDO_GEOMETRY(");&lt;br /&gt;   sb.Append((sdo_gtype != null) ? sdo_gtype.ToString() : "null");&lt;br /&gt;   sb.Append(",");&lt;br /&gt;   sb.Append((sdo_srid != null) ? sdo_srid.ToString() : "null");&lt;br /&gt;   sb.Append(",");&lt;br /&gt;   // begin point&lt;br /&gt;   if (sdo_point != null)&lt;br /&gt;   {&lt;br /&gt;    sb.Append("MDSYS.SDO_POINT_TYPE(");&lt;br /&gt;    string _tmp = string.Format("{0:0.0#####},{1:0.0#####}{2}{3:#.######}",&lt;br /&gt;            sdo_point.X,&lt;br /&gt;            sdo_point.Y,&lt;br /&gt;            (sdo_point.Z == null) ? null : ",",&lt;br /&gt;            sdo_point.Z);&lt;br /&gt;    &lt;br /&gt;    sb.Append(_tmp.Trim());&lt;br /&gt;    sb.Append(")");&lt;br /&gt;   }&lt;br /&gt;   else&lt;br /&gt;   {&lt;br /&gt;    sb.Append("null");&lt;br /&gt;   }&lt;br /&gt;   sb.Append(",");&lt;br /&gt;   // begin element array&lt;br /&gt;   if (elemArray != null)&lt;br /&gt;   {&lt;br /&gt;    sb.Append("MDSYS.SDO_ELEM_INFO_ARRAY(");&lt;br /&gt;    for (int i = 0; i &lt; elemArray.Length; i++)&lt;br /&gt;    {&lt;br /&gt;     string _tmp = string.Format("{0}", elemArray[i]);&lt;br /&gt;     sb.Append(_tmp);&lt;br /&gt;     if (i &lt; (elemArray.Length - 1))&lt;br /&gt;      sb.Append(",");&lt;br /&gt;    }&lt;br /&gt;    sb.Append(")");&lt;br /&gt;   }&lt;br /&gt;   else&lt;br /&gt;   {&lt;br /&gt;    sb.Append("null");&lt;br /&gt;   }&lt;br /&gt;   sb.Append(",");&lt;br /&gt;   // begin ordinates array&lt;br /&gt;   if (ordinatesArray != null)&lt;br /&gt;   {&lt;br /&gt;    sb.Append("MDSYS.SDO_ORDINATE_ARRAY(");&lt;br /&gt;    for (int i = 0; i &lt; ordinatesArray.Length; i++)&lt;br /&gt;    {&lt;br /&gt;     string _tmp = string.Format("{0:0.0######}", ordinatesArray[i]);&lt;br /&gt;     sb.Append(_tmp);&lt;br /&gt;     if (i &lt; (ordinatesArray.Length - 1))&lt;br /&gt;      sb.Append(",");&lt;br /&gt;    }&lt;br /&gt;    sb.Append(")");&lt;br /&gt;   }&lt;br /&gt;   else&lt;br /&gt;   {&lt;br /&gt;    sb.Append("null");&lt;br /&gt;   }&lt;br /&gt;   sb.Append(")");&lt;br /&gt;   return sb.ToString();&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; public override string ToString()&lt;br /&gt; {&lt;br /&gt;  return this.AsText;&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here is the conceptual paradigm that I chose for this iteration:&lt;br /&gt;&lt;Strong&gt;An Autodesk drawable entity decomposes into one or more SDO_ELEM_INFO_ARRAY triplet(s) with corresponding ordinates. An Autodesk drawable entity may be composed of one or more SDO_ELEM_INFO_ARRAY triplet(s) with corresponding ordinates.&lt;/strong&gt;&lt;br /&gt;With this mental shift from my original tool which is based upon a one-to-one/entity-to-sdogeometry relationship things flowed pretty well. Frankly this was a necessary shift in thinking to support the MULTI types.&lt;br /&gt;So a class "DrawAble" is composed of "DrawAbleSubComponent"(s) and DrawAbleSubComponents equate to SDO_ELEM_INFO_ARRAY triplet(s) and their corresponding ordinates.&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;    [Serializable]&lt;br /&gt;    public class DrawAbleSubComponent&lt;br /&gt;    {&lt;br /&gt;        public int[] Elem;&lt;br /&gt;        public decimal[] Ords;&lt;br /&gt;        public DrawAbleSubComponentEType Etype;&lt;br /&gt;    }//eoc DrawAbleSubComponent&lt;br /&gt; &lt;br /&gt;    [Serializable]&lt;br /&gt;    public class DrawAble&lt;br /&gt;    {&lt;br /&gt;        private DrawAbleType m_drawtype;&lt;br /&gt;        public DrawAbleType DrawEtype &lt;br /&gt;        { get{return m_drawtype;} set { m_drawtype = value; }}&lt;br /&gt;        &lt;br /&gt;        private int m_dimensionality = 2;&lt;br /&gt;        public int Dimensionality&lt;br /&gt;        { get { return m_dimensionality; } set { m_dimensionality = value; } }&lt;br /&gt;&lt;br /&gt;        public List&lt;DrawAbleSubComponent&gt; SubComponents = new List&lt;DrawAbleSubComponent&gt;();&lt;br /&gt;        public DrawAble(DrawAbleType _type, int _dimensionality)&lt;br /&gt;        {&lt;br /&gt;            DrawEtype = _type;&lt;br /&gt;            Dimensionality = _dimensionality;&lt;br /&gt;        }&lt;br /&gt;    }//eoc DrawAble &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To be continued ...&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-6220803805093138150?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/6220803805093138150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2009/11/new-sdogeometry-autodesk-map3d-2010.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/6220803805093138150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/6220803805093138150'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2009/11/new-sdogeometry-autodesk-map3d-2010.html' title='(I) New SDO_GEOMETRY &lt;-&gt; Autodesk Map3d 2010'/><author><name>Dennis Jonio</name><uri>http://www.blogger.com/profile/14478827118325682041</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-1710150409547999852</id><published>2009-01-20T20:13:00.005+01:00</published><updated>2009-02-12T18:00:29.837+01:00</updated><title type='text'>SDO_GEOMETRY - FROM and TO Autodesk Map3d</title><content type='html'>&lt;div&gt;Author: Jonio, Dennis&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;This Visual Studio 2005 solution contains everything you need to PUT/GET 2d curve SDO_GEOMETRY from/to Autodesk Map3d. It is of course a named-pipe solution. I have tested this particular one briefly on both Map3d 2008 and Map3d 2009. No warranties about anything. I have not included my SDO_GEOMETRY Validation class and anything having to do with SDO_DIM_ARRAY. This is posted elsewhere. &lt;br /&gt;What you will need: Visual Studio 2005, Map3d 2008/2009, ODP.NET 11g.&lt;br /&gt;The last and most significant new code included here is the &lt;strong&gt;DwgReader&lt;/strong&gt; and the &lt;strong&gt;DwgWriter&lt;/strong&gt; classes. They are nothing more than convenience containers for the geometry conversion methods contained with these same named classes.  &lt;br /&gt;As I have learned the idiosyncrasies and subtleties of doing conversions from one geometry system to the other are immense. For example: Circles ... what about circles? Just pursue this one issue yourself and you should become somewhat befuddled at what approach to take.&lt;br /&gt;I am aware that the conversion routine for inner and outer rings of polygons is somewhat flawed in that it does not handle ring direction properly in all cases. This has not been a big concern for me since every piece of production geometry I create gets passed through a "validator" and in the case of ring orientation SDO_MIGRATE.TO_CURRENT works fine for fix up. This was another of those lessons learned. You should always check the geometry you are going to convert. If you were not aware already, you can easily create polygon geometry in Map3d that nothing but Map3d will understand. It is what it is.&lt;br /&gt;&lt;br /&gt;The NETLOADable dll is ADSKDATABRIDGE.dll and the commandline command is: DOPUTGET.&lt;br /&gt;&lt;br /&gt;Startup “ClientBasicIO.exe” and your off and running.&lt;br /&gt;&lt;br /&gt;I have included the file “AGEOM1.sds” with the project. This is a serialized .NET dataset with a few geometries. You can load it within clientbasicio.exe.&lt;br /&gt;&lt;br /&gt;Enough … code speaks for itself …&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;You can download the solution here: &lt;a href="http://tf-net.googlecode.com/files/aPub.zip"&gt;http://tf-net.googlecode.com/files/aPub.zip&lt;/a&gt;&lt;/div&gt;&lt;strong&gt;&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-1710150409547999852?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/1710150409547999852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2009/01/sdogeomtry-from-and-to-autodesk-map3d.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/1710150409547999852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/1710150409547999852'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2009/01/sdogeomtry-from-and-to-autodesk-map3d.html' title='SDO_GEOMETRY - FROM and TO Autodesk Map3d'/><author><name>Dennis Jonio</name><uri>http://www.blogger.com/profile/14478827118325682041</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-187623275637624552</id><published>2008-11-15T18:05:00.005+01:00</published><updated>2008-11-18T10:34:06.878+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='named pipes map3d'/><title type='text'>A Simple Named Pipes Solution for Autodesk Map3d</title><content type='html'>&lt;div&gt;Author: Jonio, Dennis&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;I have recently decided to put together a minimalist IPC namedpipes application. I just could not think of something simplier than what I have here. This is like using a 747 jetliner to commute cross town to work but it does illustrate the ease. It is a complete, zipped up, Visual Studio 2005 solution with the entire source that I have outlined in other posts. To reiterate I use Map3d 2008 and have not tested this against vanilla AutoCAD. You will have to tell me if it works or not. I have no dependences on Map3d that I can think of.&lt;br /&gt;&lt;br /&gt;The NETLOADable dll is, you guessed it, IPCSimple.dll. Load it up and commandline: doit. The “DataBridge” form is minimized at startup.&lt;br /&gt;&lt;br /&gt;Startup “ClientBasicIO.exe” it is pretty obvious what to do from this point.&lt;br /&gt;&lt;br /&gt;Most of what is happening I consider pretty much to be “boilerplate”, again thanks to Ivan Latunov. My particular implementation of serializing/de-serializing the datasets can easily be changed to support whatever construction you like. Sending a text string for “SendStringToExecute” is really kind’a sort’a silly but, like I said, I could not think of anything simpler.&lt;br /&gt;&lt;br /&gt;At this point it is up to your imaginations as to how this can work for you. …enjoy! &lt;/div&gt;&lt;br /&gt;&lt;div&gt; &lt;/div&gt;&lt;br /&gt;&lt;div&gt;You can download the solution here: &lt;a href="http://tf-net.googlecode.com/files/IPCSimple.zip"&gt;http://tf-net.googlecode.com/files/IPCSimple.zip&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-187623275637624552?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/187623275637624552/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2008/11/simple-named-pipes-solution-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/187623275637624552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/187623275637624552'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2008/11/simple-named-pipes-solution-for.html' title='A Simple Named Pipes Solution for Autodesk Map3d'/><author><name>Dennis Jonio</name><uri>http://www.blogger.com/profile/14478827118325682041</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-334267185190711741</id><published>2008-11-14T10:34:00.037+01:00</published><updated>2008-11-17T12:25:44.082+01:00</updated><title type='text'>Org.OpenGIS.GeoAPI Revisited - Part I</title><content type='html'>Author: Sestic, Maksim&lt;br /&gt;&lt;br /&gt;I've been thinking of starting this article by lamenting on current state of the available managed &lt;a href="http://geoapi.sourceforge.net/"&gt;OGC's GeoAPI &lt;/a&gt;interface implementations, but I won't :-) If you're reading this - you have probably already hit their limitations. I'm talking about GeoAPI interface &lt;em&gt;ports&lt;/em&gt; here (a la &lt;a href="http://www.codeplex.com/GeoAPI"&gt;GeoAPI.NET&lt;/a&gt;), not concrete implementations (i.e. &lt;a href="http://code.google.com/p/nettopologysuite/"&gt;NetTopologySuite&lt;/a&gt;, &lt;a href="http://www.codeplex.com/SharpMap"&gt;SharpMap&lt;/a&gt; or &lt;a href="http://www.codeplex.com/ProjNET"&gt;Proj.NET&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Not having common managed interface library makes things a lot harder for GIS developers. Present one(s) won't help you much either - most of them got way out of synch when compared to their Java-based raw model maintaned by &lt;a href="http://www.opengeospatial.org/standards"&gt;OGC&lt;/a&gt;. In the meantime, Microsoft's .NET Framework itself evolved a lot, etc. To cut the long story short, my idea was to start managed GeoAPI interfaces from scratch, based on present &lt;a href="http://maven.geotools.fr/repository/org/opengis/geoapi/2.1.1/"&gt;GeoAPI 2.1.1&lt;/a&gt; interfaces specification - but not by simply jumping into it...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;Naming Conventions&lt;/strong&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Lets start with something "obvious" - naming conventions used in Java and .NET. For example: &lt;span style="font-family:courier new;"&gt;org.opengis.geometry&lt;/span&gt; namespace becomes &lt;span style="font-family:courier new;"&gt;Org.OpenGIS.Geometry&lt;/span&gt; namespace in .NET. Both camel-case and abbreviation rules apply, starting letter always capitalized.&lt;br /&gt;&lt;br /&gt;When it comes to interface names, since it's mostly about them, each Java class pertaining to an interface gets an "I" prefix. For example: &lt;span style="font-family:courier new;"&gt;Precision&lt;/span&gt; interface becomes &lt;span style="font-family:courier new;"&gt;IPrecision&lt;/span&gt; in .NET.&lt;br /&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;Naming and Type Conventions&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Java Get/Set functions become Properties. That is - ReadOnly properties for explicit getter functions, or WriteOnly properties for explicit setter functions. Also, get/set prefix gets stripped from resulting property name, always starting with a capital letter. For example:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function getLength() As Double&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;becomes:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ReadOnly Property Length() As Double&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Also:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function getLength() As Double&lt;br /&gt;Sub setLength(d As Double)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;method pair becomes:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Property Length() As Double&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So, when Java function becomes .NET property, and when it simply remains a method - beyond getter/setter rules stated above? It depends on overall method semantics; what it actually means to hosting class/object. For example:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function setLength(d As Double)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;when alone in a class, becomes:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;WriteOnly Property Length() As Double&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Because Length is a class property. But:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function ToArray() As Double()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;remains a function, since it's a method to hosting class. Sticking to described semantic rules, even parametrized functions become properties. For example:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function getBuffer(d As Double) As IGeometry&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;becomes:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ReadOnly Property Buffer(ByVal d As Double) As IGeometry&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;since buffer is a parametrized geometric property (one of many, of course).&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;Type Conventions And Enumerators&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Enumerated types seem rather confusing to present managed GeoAPI ports. In fact, they're simple enumerators. A good example for this is &lt;span style="font-family:courier new;"&gt;org.opengis.geometry.PrecisionType&lt;/span&gt; which derives from (extends) generic Java &lt;span style="font-family:courier new;"&gt;CodeList&lt;/span&gt; type. In .NET it becomes:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Public Enum PrecisionType&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;with it's members slightly changed when it comes to naming: &lt;span style="font-family:courier new;"&gt;DOUBLE&lt;/span&gt; becomes &lt;span style="font-family:courier new;"&gt;Double&lt;/span&gt;, &lt;span style="font-family:courier new;"&gt;FIXED&lt;/span&gt; becomes &lt;span style="font-family:courier new;"&gt;Fixed&lt;/span&gt;, etc. If we had a Java member named &lt;span style="font-family:courier new;"&gt;PIECEWISE_BEZIER&lt;/span&gt;, then it would become &lt;span style="font-family:courier new;"&gt;PiecewiseBezier&lt;/span&gt; in .NET. BTW, proposed notation is way closer to original ISO identifier naming rules anyways.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;Type Conventions And Generics&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This is the most challening part of it all. That's also why &lt;a href="http://www.ikvm.net/"&gt;IKVM.NET&lt;/a&gt; won't help you much with GeoAPI in first place. Yes, it's about .NET generics and how do we use them in GeoAPI - keeping in mind future implementations. IMHO, it's very important to introduce strongly typed collections to managed GeoAPI interfaces. Alas, without knowing the nature of each interface it's close to impossible to introduce their generic counterparts properly. In other words - one needs to consult UML definition and think ahead of possible implications on implementers' side.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;Ongoing Activities&lt;/strong&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;You can check the current development status of managed GeoAPI library based on present GeoAPI 2.1.1 interfaces specification here: &lt;a href="http://code.google.com/p/geoapi-mgd/" name="Managed_OpenGIS_GeoAPI_Interfaces"&gt;Managed OpenGIS GeoAPI Interfaces&lt;/a&gt; (look under SVN trunk).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-334267185190711741?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/334267185190711741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2008/11/orgopengisgeoapi-revisited-part-i.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/334267185190711741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/334267185190711741'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2008/11/orgopengisgeoapi-revisited-part-i.html' title='Org.OpenGIS.GeoAPI Revisited - Part I'/><author><name>Maksim Sestic</name><uri>http://www.blogger.com/profile/11155932635442483931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-503233300439218710</id><published>2008-11-04T21:51:00.036+01:00</published><updated>2008-11-05T16:39:54.559+01:00</updated><title type='text'>Extending the IGeometryCollection type with methods provided on the HashSet(T) class</title><content type='html'>&lt;span style="font-size:130%;color:#333333;"&gt;Author: Baxevanis, Nikos&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:130%;color:#333333;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-size:130%;color:#333333;"&gt;Overview &lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;span style="color:#000000;"&gt;As of Kim Hamilton’s post&lt;/span&gt;, &lt;a href="http://blogs.msdn.com/bclteam/archive/2006/11/09/introducing-hashset-t-kim-hamilton.aspx"&gt;http://blogs.msdn.com/bclteam/archive/2006/11/09/introducing-hashset-t-kim-hamilton.aspx&lt;/a&gt; &lt;span style="color:#000000;"&gt;&lt;em&gt;“HashSet determines equality according to the EqualityComparer you specify, or the default EqualityComparer for the type (if you didn’t specify)”.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;The IGeometryCollection type implements the IComparable(T). Using extension methods we “add” methods from the HashSet(T) class so any type that implements the IGeometryCollection appears to have instance methods such as IntersectWith, UnionWith etc. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;p align="center"&gt;&lt;img id="BLOGGER_PHOTO_ID_5264909591608792578" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 224px; CURSOR: hand; HEIGHT: 145px; TEXT-ALIGN: center" alt="" src="http://2.bp.blogspot.com/_gjVAC0OfHbo/SRC3YP5jlgI/AAAAAAAAAAM/rRkunyJVP9I/s320/IComparable(IGeometry).jpg" border="0" /&gt;&lt;span style="font-size:78%;"&gt;&lt;em&gt;The IGeometryCollection type implements the IComparable(T).&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style="color:#000000;"&gt;A HashSet(T) operation modifies the set it’s called on and doesn’t create a new set. The extension methods provided with this article return an IGeometryCollection object rather than modifying the caller set.&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:130%;color:#333333;"&gt;&lt;strong&gt;Implementation &lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;em&gt;&lt;span style="color:#000000;"&gt;“Extension methods are defined as static methods but are called by using instance method syntax. Their first parameter specifies which type the method operates on, and the parameter is preceded by the this modifier. Extension methods are only in scope when you explicitly import the namespace into your source code with a using directive.” &lt;a href="http://msdn.microsoft.com/en-us/library/bb359438.aspx"&gt;http://msdn.microsoft.com/en-us/library/bb359438.aspx&lt;/a&gt;&lt;/span&gt;&lt;/em&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-size:130%;color:#333333;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-size:130%;color:#333333;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;        public static Topology.Geometries.IGeometryCollection UnionWith(this Topology.Geometries.IGeometryCollection geomCol, Topology.Geometries.IGeometryCollection otherCol)&lt;br /&gt;        {&lt;br /&gt;            return Operation(geomCol, otherCol, OperationType.Union);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public static Topology.Geometries.IGeometryCollection IntersectWith(this Topology.Geometries.IGeometryCollection geomCol, Topology.Geometries.IGeometryCollection otherCol)&lt;br /&gt;        {&lt;br /&gt;            return Operation(geomCol, otherCol, OperationType.Intersection);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static Topology.Geometries.IGeometryCollection Operation(Topology.Geometries.IGeometryCollection geomCol, Topology.Geometries.IGeometryCollection otherCol, OperationType typeOp)&lt;br /&gt;        {&lt;br /&gt;            HashSet&lt;topology.geometries.igeometry&gt; geomSet =&lt;br /&gt;               new HashSet&lt;topology.geometries.igeometry&gt;();&lt;br /&gt;&lt;br /&gt;            foreach (Topology.Geometries.IGeometry geom in geomCol)&lt;br /&gt;                geomSet.Add(geom);&lt;br /&gt;&lt;br /&gt;            HashSet&lt;topology.geometries.igeometry&gt; otherSet =&lt;br /&gt;                new HashSet&lt;topology.geometries.igeometry&gt;();&lt;br /&gt;&lt;br /&gt;            foreach (Topology.Geometries.IGeometry geom in otherCol)&lt;br /&gt;                otherSet.Add(geom);&lt;br /&gt;&lt;br /&gt;            switch (typeOp)&lt;br /&gt;            {&lt;br /&gt;                case OperationType.Intersection:&lt;br /&gt;                    geomSet.IntersectWith(otherSet);&lt;br /&gt;                    break;&lt;br /&gt;&lt;br /&gt;                case OperationType.Union:&lt;br /&gt;                    geomSet.UnionWith(otherSet);&lt;br /&gt;                    break;&lt;br /&gt;&lt;br /&gt;                case OperationType.Except:&lt;br /&gt;                    geomSet.ExceptWith(otherSet);&lt;br /&gt;                    break;&lt;br /&gt;&lt;br /&gt;                case OperationType.SymmetricExcept:&lt;br /&gt;                    geomSet.SymmetricExceptWith(otherSet);&lt;br /&gt;                    break;&lt;br /&gt;&lt;br /&gt;                default:&lt;br /&gt;                    return Topology.Geometries.GeometryCollection.Empty;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            Topology.Geometries.IGeometry[] array =&lt;br /&gt;               new Topology.Geometries.IGeometry[geomSet.Count];&lt;br /&gt;&lt;br /&gt;            geomSet.CopyTo(array);&lt;br /&gt;&lt;br /&gt;            return new Topology.Geometries.GeometryFactory().CreateGeometryCollection(array);&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-size:130%;color:#333333;"&gt;&lt;strong&gt;Using the extension methods in your code&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#000000;"&gt;You have to add a reference to &lt;em&gt;Topology.Geometries.GeometryCollectionExtensions.dll&lt;/em&gt;&lt;br /&gt;To use the HashSet(T) operations first bring them into scope with a using &lt;em&gt;Topology.Geometries.GeometryCollectionExtensions&lt;/em&gt; directive. &lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p align="center"&gt;&lt;img id="BLOGGER_PHOTO_ID_5264910161500903714" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 160px; CURSOR: hand; HEIGHT: 170px; TEXT-ALIGN: center" alt="" src="http://3.bp.blogspot.com/_gjVAC0OfHbo/SRC35a6bGSI/AAAAAAAAAAU/TL6Gp6HFIyQ/s320/Members.jpg" border="0" /&gt;&lt;em&gt;&lt;span style="font-size:78%;"&gt;Using the HashSet(T) operations&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="left"&gt;&lt;/p&gt;&lt;p align="left"&gt;&lt;/p&gt;&lt;p align="left"&gt;&lt;/p&gt;&lt;p align="left"&gt;&lt;/p&gt;&lt;p align="left"&gt;Available for download here: &lt;a href="http://tf-net.googlecode.com/files/GeometryCollectionExtensions-Source.zip"&gt;http://tf-net.googlecode.com/files/GeometryCollectionExtensions-Source.zip&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-503233300439218710?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/503233300439218710/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2008/11/extending-igeometrycollection-type-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/503233300439218710'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/503233300439218710'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2008/11/extending-igeometrycollection-type-with.html' title='Extending the IGeometryCollection type with methods provided on the HashSet(T) class'/><author><name>Nikos Baxevanis</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_gjVAC0OfHbo/TTv9pr6ASqI/AAAAAAAAACU/29siTwi1ft4/s220/Myself.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_gjVAC0OfHbo/SRC3YP5jlgI/AAAAAAAAAAM/rRkunyJVP9I/s72-c/IComparable(IGeometry).jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-652122425106956662</id><published>2008-10-28T13:17:00.032+01:00</published><updated>2008-11-03T17:18:25.103+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IPC Map3d communication namedpipes'/><title type='text'>Inter-Process Communication (IPC) with Autodesk Map3d</title><content type='html'>Author: Jonio, Dennis&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Prospective and Environment&lt;/strong&gt;&lt;br /&gt;Everything that follows was done on and with Windows XP SP2, Visual Studio 2005 Professional SP1, Oracle XE 10.2, Oracle ODP.NET 11g(2.111.6.20), Autodesk Map3d 2008 SP1, Autodesk ObjectARX 2008 and lots of reading and lots of research. Since I have not done it myself I cannot attest as to the viability of this solution in a vanilla AutoCAD 200x environment. I am however inclined to believe that it will work just fine. I make neither guarantees nor claims of fitness for any purpose. It is “as-is” so proceed at your own risk.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Overview&lt;/strong&gt;&lt;br /&gt;Simply stated, this was the problem, I wished to have a generic way in which to communicate with a DWG. All I wished to do was PUT an SDO_GEOMETRY and GET a selected entity back as an SDO_GEOMETRY. This seemed to me to be a not unreasonable request. Just think about this a second: AutoCAD as a COLUMN editor? I could build whatever user interface I wished, using whatever tools I wished. Include all the business logic needed and then just “plumb” this stand-alone application. I didn’t have to solve the world’s problems either. Points, lines and surfaces were all I was interested in. Well good luck! First off there was no .NET DWG to SDO_GEOMETRY translator that I could get my hands on. Second, this just is not how Autodesk has written their applications. Don’t misunderstand me here. This is not a flame against Autodesk. Their applications do what they were designed to do and do this very well. So this series is then about getting one of two major things accomplished: 1) A 2-dimensional, SDO_GEOMETRY translator that supported arcs and 2) A communications interface.&lt;br /&gt;&lt;br /&gt;This is about the communications piece. In my mind this would be the most technically challenging and if I was going to fail it would be on this.&lt;br /&gt;&lt;br /&gt;Of course the issue of multithreading arose numerous times but it always seemed, by its nature, to be somewhat limiting. Inter-process communication (IPC) was the answer but I found no ready made solution. I had to piece this together myself. I did a fair amount of investigating and found named pipes to be the most generic and robust approach to take.&lt;br /&gt;&lt;br /&gt;This is not really a story about pipes but you must look at this article: &lt;u&gt;“Inter-Process Communication in .NET Using Named Pipes” by &lt;em&gt;Ivan Latunov&lt;/em&gt;&lt;/u&gt;.&lt;br /&gt;&lt;a href="http://www.codeproject.com/KB/threads/dotnetnamedpipespart1.aspx"&gt;link to article &lt;/a&gt; The author explains it all much better than I ever could and his implementation is the backbone of this implementation. By the way, I believe that Microsoft has now included Named Pipe support in the 3.5 .NET framework. Since MS pipes are a Client/Server architecture and I was totally intimidated by “overlapping” ,“bidirectional” and the other more complex implementations I decided to really simplify and incorporate, in each executable or dll, a pipe Server and a pipe Client. Thank you Ivan. The significant change that I incorporated was the use of Events on the Server side( the “owner” side if you will ). When you compare Ivan’s code to mine you will see some other minor changes. A simple piccy to illustrate the idea.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://4.bp.blogspot.com/_tM5lW6vfyRw/SQcFVdSFXyI/AAAAAAAAAAM/6wBZFaJoVFU/s1600-h/vis_aid00.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5262180555801583394" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 320px; CURSOR: hand; HEIGHT: 149px; TEXT-ALIGN: center" alt="" src="http://4.bp.blogspot.com/_tM5lW6vfyRw/SQcFVdSFXyI/AAAAAAAAAAM/6wBZFaJoVFU/s320/vis_aid00.gif" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Since experience has taught me that the Autodesk API’s are not trivial especially when it comes to the MDI interface structure I really needed to isolate this application as much as possible. The solution was a simple data exchange mechanism, a data “bridge”, if you will. Let the bridge become the generic between the other executables! My NETLOADed module and the “bridge” will communicate with simple Events and Queue objects! The Autodesk API’s understands Forms, Forms are, by nature, multi-threaded! The bridge will then communicate to whatever is at the other end of the pipe. BINGO! We have it all!&lt;br /&gt;&lt;br /&gt;Below is a clip where these ideas are put together. Very simple and straightforward but it should give you some "food for thought":&lt;br /&gt;&lt;br /&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-38be9ce4b292372c" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v9.nonxt8.googlevideo.com/videoplayback?id%3D38be9ce4b292372c%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1332439359%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D7E1B36C678F29B5C9BD67B638791A5652762CC4C.3183996EA5AF6408F19C81F60A34F958359772E1%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D38be9ce4b292372c%26offsetms%3D5000%26itag%3Dw160%26sigh%3D4iUYOk-KQr8B9cmFJVXjPVE4R8U&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="320" height="266" bgcolor="#FFFFFF"flashvars="flvurl=http://v9.nonxt8.googlevideo.com/videoplayback?id%3D38be9ce4b292372c%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1332439359%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D7E1B36C678F29B5C9BD67B638791A5652762CC4C.3183996EA5AF6408F19C81F60A34F958359772E1%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D38be9ce4b292372c%26offsetms%3D5000%26itag%3Dw160%26sigh%3D4iUYOk-KQr8B9cmFJVXjPVE4R8U&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;/p&gt;&lt;p&gt;Full-size video clip is available for download at:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://tf-net.googlecode.com/files/ipc_acad_sdo.rar"&gt;http://tf-net.googlecode.com/files/ipc_acad_sdo.rar&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;The Communications Data Definition&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;OK… so now we have settled on the communications “plumbing”, a full blown IO channel no less, what is it that we wish to communicate?&lt;br /&gt;Well in reading Ivan’s work and the work of some others I became aware that pipes can move megabytes of data in sub-second times. Thusly then, the amount was not the issue the format was. Whatever that format was it had to be serializable and it had to be generic. I had to accomplish two(2) things: 1) construct a request that I wished my NETLOADed module to perform 2) provide for data interchange. The solution here is a plain’ol .NET dataset. In fact, all I really had to do was encapsulate a dataset inside a field in a “control” dataset. I could then pass one(1) serializabe object that had both a request/task and corresponding data. In my mind at least, very clean, very straightforward, and very generic.&lt;br /&gt;&lt;br /&gt;The following is the structure I decided upon for my environment:&lt;br /&gt;&lt;/p&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;public static DataSet MaterializeNPControlDataSet()&lt;br /&gt;    {&lt;br /&gt;    DataSet _ds = new DataSet("NPCONTROLDATASET");&lt;br /&gt;    _ds.RemotingFormat = SerializationFormat.Binary;&lt;br /&gt;    _ds.SchemaSerializationMode = SchemaSerializationMode.IncludeSchema;&lt;br /&gt;&lt;br /&gt;    _ds.Tables.Add("NPCONTROLTABLE");&lt;br /&gt;    DataColumn dc1 = new DataColumn("ID", typeof(Int32));&lt;br /&gt;    DataColumn dc2 = new DataColumn("TEXT", typeof(string));&lt;br /&gt;    DataColumn dc3 = new DataColumn("PAYLOADTEXT", typeof(string));&lt;br /&gt;    DataColumn dc4 = new DataColumn("PAYLOAD", typeof(object));&lt;br /&gt;    _ds.Tables[0].Columns.Add(dc1);&lt;br /&gt;    _ds.Tables[0].Columns.Add(dc2);&lt;br /&gt;    _ds.Tables[0].Columns.Add(dc3);&lt;br /&gt;    _ds.Tables[0].Columns.Add(dc4);&lt;br /&gt;    return _ds;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To support the manipulation of this structure there is one(1) class. All of the serialization/de-seriaization and encapsulations are done with this class. Below are the “putter” and “getter” methods for the dataset that is encapsulated within the “PAYLOAD” field. In addition there are numerous other helper methods within the class.&lt;br /&gt;”putter”&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;public static void SetNPControlTablePayLoad(ref DataSet _NPds, ref DataSet _payload)&lt;br /&gt;    {&lt;br /&gt;        byte[] ba = SerializeDataSet(ref _payload);&lt;br /&gt;        _NPds.Tables["NPCONTROLTABLE"].Rows[0]["PAYLOAD"] = (object)ba;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;“getter”&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;public static DataSet ExtractNPCTablePayLoad(ref DataSet _NPds)&lt;br /&gt;    {&lt;br /&gt;        DataSet ads = null;&lt;br /&gt;        object o = (object)_NPds.Tables["NPCONTROLTABLE"].Rows[0]["PAYLOAD"];&lt;br /&gt;        if (o != System.DBNull.Value)&lt;br /&gt;        {&lt;br /&gt;            ads = ExtractSerializedDataSet((byte[])o);&lt;br /&gt;            if (ads != null)&lt;br /&gt;                return ads;&lt;br /&gt;            else&lt;br /&gt;                return null;&lt;br /&gt;        }&lt;br /&gt;            else&lt;br /&gt;                return null;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;No, I did not implement any compression of the datasets, just the BinaryFormatter.&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;       public static byte[] SerializeDataSet(ref DataSet _ds)&lt;br /&gt;        {&lt;br /&gt;            _ds.RemotingFormat = SerializationFormat.Binary;&lt;br /&gt;            _ds.SchemaSerializationMode = SchemaSerializationMode.IncludeSchema;&lt;br /&gt;            MemoryStream ms = new MemoryStream();&lt;br /&gt;            BinaryFormatter bf = new BinaryFormatter();&lt;br /&gt;            bf.Serialize(ms, _ds);&lt;br /&gt;            if (ms.Length &gt; 0)&lt;br /&gt;                return ms.ToArray();&lt;br /&gt;            else&lt;br /&gt;                return null;&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;strong&gt;The Named Pipes&lt;/strong&gt;&lt;br /&gt;Ivan’s implementation is a work of art. I really hated to touch it. (Not only because it was well put together but I really did not fully comprehend his threading architecture). However, I really needed event hooks because this wasn’t going to be a “classic” Client/Server application. The applications that were going to be incorporating this were going to be operating in and supporting the user interface world. Since Ivan had architected this with interfaces I went about some touch up. (four lines of code with some big ideas ...)&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;using System;&lt;br /&gt;namespace AppModule.InterProcessComm {&lt;br /&gt;    // Delegates for events that your component will use to communicate&lt;br /&gt;    // values to the form&lt;br /&gt;     public delegate void ReceiveCompleteHandler(byte[] ba);&lt;br /&gt;     public delegate void StatusActivityHandler(string info);&lt;br /&gt;&lt;br /&gt;public interface IChannelManager {&lt;br /&gt;        // events that this (class)component will use to communicate with the app&lt;br /&gt;        event ReceiveCompleteHandler OnReceiveComplete;&lt;br /&gt;        event StatusActivityHandler OnStatusActivity;&lt;br /&gt;&lt;br /&gt;  void Initialize();&lt;br /&gt;  void Stop();&lt;br /&gt;  string HandleRequest(string request);&lt;br /&gt;  bool Listen {get; set;}&lt;br /&gt;  void WakeUp();&lt;br /&gt;        void RemoveServerChannel(object param);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Since I had decided to have both a Client and a Server incorporated within each app I made it easier on myself and just constructed an “A” and “B” dispatcher (I wanted to get rid of this Client/Server label). One would be owned by the “bridge” the other would be owned by the “other” application.&lt;br /&gt;They are really nothing more than containers for Ivan’s &lt;strong&gt;public static IChannelManager PipeManager;&lt;/strong&gt; I just added a few constants to make life easier and to set the “ReadOn” pipe and the “SendOn” pipe. I really didn’t want any confusion later on.&lt;br /&gt;&lt;br /&gt;PipeManager’s most significant modifications had to do with the Events hooks:&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;if (numChannels &lt;= NumberPipes) // =&gt;&lt;br /&gt;{&lt;br /&gt; ServerNamedPipe pipe = new ServerNamedPipe(PipeName, OutBuffer, InBuffer, MAX_READ_BYTES, false);&lt;br /&gt; // subscribe to the events raised when data has been gotten&lt;br /&gt; pipe.GotNewByteArray += new OnNewByteArrayHandler(pipe_GotNewByteArray);&lt;br /&gt; pipe.GotActivity += new OnActivityToReportHandler(pipe_GotActivity);&lt;br /&gt; try&lt;br /&gt; {&lt;br /&gt;  pipe.Connect();&lt;br /&gt;  pipe.LastAction = DateTime.Now;&lt;br /&gt;  System.Threading.Interlocked.Increment(ref numChannels);&lt;br /&gt;  pipe.Start();&lt;br /&gt;  Pipes.Add(pipe.PipeConnection.NativeHandle, pipe);&lt;br /&gt; }&lt;br /&gt; catch (InterProcessIOException ex) {&lt;br /&gt;  RemoveServerChannel(pipe.PipeConnection.NativeHandle);&lt;br /&gt;  // unsubscribe to the events raised when data has been gotten&lt;br /&gt;  pipe.GotNewByteArray -= new OnNewByteArrayHandler(pipe_GotNewByteArray);&lt;br /&gt;  pipe.GotActivity -= new OnActivityToReportHandler(pipe_GotActivity);&lt;br /&gt;  pipe.Dispose();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;else {&lt;br /&gt; Mre.Reset();&lt;br /&gt; Mre.WaitOne(1000, false);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, I just pass it on up the chain to “whatever” has hooked up.&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;void pipe_GotActivity(object sender, string activity)&lt;br /&gt;{&lt;br /&gt; if (OnStatusActivity.Target is System.Windows.Forms.Control)&lt;br /&gt;    {&lt;br /&gt;       // make sure execution is done on the UI thread&lt;br /&gt;       System.Windows.Forms.Control t = OnStatusActivity.Target as System.Windows.Forms.Control;&lt;br /&gt;             t.BeginInvoke(OnStatusActivity, new Object[] { activity });&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;        // object from the invocation list isn't a UI thread.&lt;br /&gt;        OnStatusActivity(activity);&lt;br /&gt;       }&lt;br /&gt;}&lt;br /&gt;void pipe_GotNewByteArray(object sender, byte[] ba)&lt;br /&gt;{&lt;br /&gt; string rcvszdttm = string.Format("Received: {0} bytes at {1}", ba.Length.ToString(), DateTime.Now);&lt;br /&gt;    // tell whoever that a worker has just sent us a byte array&lt;br /&gt;    pipe_GotActivity(this, rcvszdttm);&lt;br /&gt;    //&lt;br /&gt;    // determine if the object on which this delegate was invoked is a UI thread&lt;br /&gt;    // if the object is a control, then the object is a UI thread&lt;br /&gt;    //&lt;br /&gt;    if (OnReceiveComplete.Target is System.Windows.Forms.Control)&lt;br /&gt;    {&lt;br /&gt;     // make sure execution is done on the UI thread&lt;br /&gt;        System.Windows.Forms.Control t = OnReceiveComplete.Target as System.Windows.Forms.Control;&lt;br /&gt;        t.BeginInvoke(OnReceiveComplete, new Object[] { ba });&lt;br /&gt;    }&lt;br /&gt;    else // object from the invocation list isn't a UI thread.&lt;br /&gt;        OnReceiveComplete(ba);        &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Finally &lt;strong&gt;public sealed class ServerNamedPipe&lt;/strong&gt; had to be tweaked. In this implementation I always send an acknowledgment string after a receipt. It is client/server after all. So it is a receive binary / send a string.&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;public event OnNewByteArrayHandler GotNewByteArray;&lt;br /&gt;public event OnActivityToReportHandler GotActivity;&lt;br /&gt; private void PipeListener() {&lt;br /&gt;  CheckIfDisposed();&lt;br /&gt;  try {&lt;br /&gt;   Listen = DspchrHandlerA.PipeManager.Listen;&lt;br /&gt;   string myName = "Pipe_" + this.PipeConnection.NativeHandle.ToString();&lt;br /&gt;   GotActivity(new object(), myName + " :new pipe started");&lt;br /&gt;   while (Listen)&lt;br /&gt;   {&lt;br /&gt;    LastAction = DateTime.Now;&lt;br /&gt;    byte[] request = PipeConnection.ReadBytes();&lt;br /&gt;    LastAction = DateTime.Now;&lt;br /&gt;    &lt;br /&gt;     // pipe manager gets the data&lt;br /&gt;     GotNewByteArray(this, request);&lt;br /&gt;     // this goes to the sender's listener to signal OK&lt;br /&gt;     PipeConnection.Write("ACKNOWLEDGEMENT " + request.Length.ToString() + " bytes");&lt;br /&gt;     //pipe manager get more info&lt;br /&gt;     GotActivity(new object(), myName + " acknowledgement sent for receipt of " + request.Length.ToString() + " bytes");&lt;br /&gt;&lt;br /&gt;    LastAction = DateTime.Now;&lt;br /&gt;    PipeConnection.Disconnect();&lt;br /&gt;    if (Listen) {&lt;br /&gt;     GotActivity(new object(), myName + " :listening");                        &lt;br /&gt;     Connect();&lt;br /&gt;    }&lt;br /&gt;    //&lt;br /&gt;    DspchrHandlerA.PipeManager.WakeUp();&lt;br /&gt;   }&lt;br /&gt;  } &lt;br /&gt;  catch (System.Threading.ThreadAbortException ex) { }&lt;br /&gt;  catch (System.Threading.ThreadStateException ex) { }&lt;br /&gt;  catch (Exception ex) { &lt;br /&gt;   // Log exception&lt;br /&gt;  }&lt;br /&gt;  finally {&lt;br /&gt;   this.Close();&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Believe me named pipes and threads are NOT my specialty. I just had to know and do just enough to make it work for me. Yes, I am sure there are different and probably better ways. But I am a pragmatist and was not doing this for fun.&lt;br /&gt;&lt;br /&gt;So we now have our pipes and we have an A and a B configuration. It matters not who is who but obviously partners cannot have the same configuration. As a final note these configurations are coded to operate on one workstation. You can of course run across different machines but that is a whole different topic.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Data Bridge&lt;/strong&gt;&lt;br /&gt;This is the Form that will be instantiated from our NETLOADed module. As I mentioned before I wanted this to be as simple and generic as possible. Just a couple public Queue objects and a few events. I did add some UI Controls to play with during debug and never took them out.&lt;br /&gt;&lt;br /&gt;How it works:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Receive an entry on “my” pipe&lt;/li&gt;&lt;li&gt;EnQueue the entry into the Suspense Queue&lt;/li&gt;&lt;li&gt;Fire off an OnReceivedQueueEntry event&lt;/li&gt;&lt;/ol&gt;OR&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Receive an OnCompletedTask event&lt;/li&gt;&lt;li&gt;DeQueue the entry from the Process queue&lt;/li&gt;&lt;li&gt;Send it on to the other “Server’&lt;/li&gt;&lt;/ol&gt;If there is a simpler approach I could not think of it. Since a picture is worth so many words…&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_jXUwIwpxWKo/SQm58cktOEI/AAAAAAAABVk/W_-jkdoDta8/s1600-h/DataBridge.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5262942087672576066" style="WIDTH: 400px; CURSOR: hand; HEIGHT: 189px" alt="" src="http://2.bp.blogspot.com/_jXUwIwpxWKo/SQm58cktOEI/AAAAAAAABVk/W_-jkdoDta8/s400/DataBridge.gif" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And the entire source sans the UI controls for the bridge:&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Data;&lt;br /&gt;using System.Drawing;&lt;br /&gt;using System.ComponentModel;&lt;br /&gt;using System.Windows.Forms;&lt;br /&gt;using System.Collections;&lt;br /&gt;&lt;br /&gt;using DspchrHandlers;&lt;br /&gt;using Dspchr;&lt;br /&gt;&lt;br /&gt;namespace DataBridge&lt;br /&gt;{&lt;br /&gt;    public partial class DataBridge : Form&lt;br /&gt;    {&lt;br /&gt;        public delegate void ReceivedQueueEntryHandler(object sender);&lt;br /&gt;        public event ReceivedQueueEntryHandler OnReceivedQueueEntry;&lt;br /&gt;&lt;br /&gt;        public Queue SuspenseQ;&lt;br /&gt;        public Queue ProcessQ;&lt;br /&gt;&lt;br /&gt;        public SendVia SendViaX;&lt;br /&gt;        IDataBridge iDataBridgeClient;&lt;br /&gt;&lt;br /&gt;        public DataBridge(IDataBridge parent)&lt;br /&gt;        {&lt;br /&gt;            InitializeComponent();&lt;br /&gt;            iDataBridgeClient = parent; &lt;br /&gt;            DspchrHandlerA.StartServer();&lt;br /&gt;            SuspenseQ = new Queue();&lt;br /&gt;            ProcessQ = new Queue();&lt;br /&gt;            SendViaX = new SendVia();&lt;br /&gt;            DspchrHandlerA.PipeManager.OnReceiveComplete += new AppModule.InterProcessComm.ReceiveCompleteHandler(PipeManager_OnReceiveComplete);&lt;br /&gt;            DspchrHandlerA.PipeManager.OnStatusActivity += new AppModule.InterProcessComm.StatusActivityHandler(PipeManager_OnStatusActivity);&lt;br /&gt;            iDataBridgeClient.OnCompletedTask += new CompletedTaskHandler(iDataBridgeClient_OnCompletedTask);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        void iDataBridgeClient_OnCompletedTask(object sender)&lt;br /&gt;        {&lt;br /&gt;            lblPQCnt.Text = ProcessQ.Count.ToString();&lt;br /&gt;            string rtn_result = null;&lt;br /&gt;            if (ProcessQ.Count &gt; 0)&lt;br /&gt;            {&lt;br /&gt;                rtn_result = SendViaX.WriteBytes(DspchrHandlerA.SendOnPipeName, DspchrHandlerA.ServerName, (byte[])ProcessQ.Dequeue());&lt;br /&gt;                txtActivity.AppendText(rtn_result + Environment.NewLine);&lt;br /&gt;            }&lt;br /&gt;            lblPQCnt.Text = ProcessQ.Count.ToString();&lt;br /&gt;            lblSQCnt.Text = SuspenseQ.Count.ToString();&lt;br /&gt;        }       &lt;br /&gt;        //&lt;br /&gt;        void PipeManager_OnStatusActivity(string info)&lt;br /&gt;        {&lt;br /&gt;            txtActivity.AppendText(info + Environment.NewLine);&lt;br /&gt;        }&lt;br /&gt;        void PipeManager_OnReceiveComplete(byte[] ba)&lt;br /&gt;        {&lt;br /&gt;            SuspenseQ.Enqueue(ba);&lt;br /&gt;            lblSQCnt.Text = SuspenseQ.Count.ToString();&lt;br /&gt;            Application.DoEvents();&lt;br /&gt;            OnReceivedQueueEntry(this);&lt;br /&gt;        } &lt;br /&gt;        private void DataBridge_FormClosing(object sender, FormClosingEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            DspchrHandlerA.StopServer();&lt;br /&gt;        }&lt;br /&gt;        //&lt;br /&gt;        // Some form relate stuff to mess around with&lt;br /&gt;        //&lt;br /&gt;        private void btnRmvSQE_Click(object sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            if (SuspenseQ.Count &gt; 0) SuspenseQ.Dequeue();&lt;br /&gt;            lblSQCnt.Text = SuspenseQ.Count.ToString();&lt;br /&gt;        }&lt;br /&gt;        private void btnRmvPQE_Click(object sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            if (ProcessQ.Count &gt; 0) ProcessQ.Dequeue();&lt;br /&gt;            lblPQCnt.Text = ProcessQ.Count.ToString();&lt;br /&gt;        }&lt;br /&gt;        private void btnReturnSQE_Click(object sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            string rtn_result = null;&lt;br /&gt;            if (SuspenseQ.Count &gt; 0)&lt;br /&gt;            {&lt;br /&gt;                rtn_result = SendViaX.WriteBytes(DspchrHandlerA.SendOnPipeName, DspchrHandlerA.ServerName, (byte[])SuspenseQ.Dequeue());&lt;br /&gt;                lblSQCnt.Text = SuspenseQ.Count.ToString();&lt;br /&gt;                txtActivity.AppendText(rtn_result + Environment.NewLine);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        private void btnCLEARLOG_Click(object sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            txtActivity.Clear();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The last piece of the puzzle is this interface object for the DataBridge so it knows that there was something to be done. &lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Text;&lt;br /&gt;&lt;br /&gt;public delegate void CompletedTaskHandler(object sender);&lt;br /&gt;public interface IDataBridge&lt;br /&gt;{&lt;br /&gt;    event CompletedTaskHandler OnCompletedTask;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;And a skeleton of a NETLOADable dll:&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;namespace ADSKDATABRIDGE&lt;br /&gt;{&lt;br /&gt;    public class WRKR : IDataBridge&lt;br /&gt;    {&lt;br /&gt;        public event CompletedTaskHandler OnCompletedTask;&lt;br /&gt;        public DataBridge.DataBridge DataBridgeForm;&lt;br /&gt;&lt;br /&gt;        private static object TestForDuplication = null;&lt;br /&gt;        public WRKR() { }&lt;br /&gt;        &lt;br /&gt;        [CommandMethod("DOPUTGET")]&lt;br /&gt;        public void dome() &lt;br /&gt;        {&lt;br /&gt;            if (TestForDuplication == null)&lt;br /&gt;            {&lt;br /&gt;                DataBridgeForm = new DataBridge.DataBridge(this);&lt;br /&gt;                TestForDuplication = DataBridgeForm;&lt;br /&gt;                DataBridgeForm.FormClosing += new FormClosingEventHandler(DataBridgeForm_FormClosing);&lt;br /&gt;                DataBridgeForm.OnReceivedQueueEntry += new DataBridge.DataBridge.ReceivedQueueEntryHandler(DataBridgeForm_OnReceivedQueueEntry);&lt;br /&gt;                DataBridgeForm.Show();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        void DataBridgeForm_FormClosing(object sender, FormClosingEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            DataBridgeForm.OnReceivedQueueEntry -= new DataBridge.DataBridge.ReceivedQueueEntryHandler(DataBridgeForm_OnReceivedQueueEntry);&lt;br /&gt;            TestForDuplication = null;&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;Finally … we receive our task and do it&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;        void DataBridgeForm_OnReceivedQueueEntry(object sender)&lt;br /&gt;        {&lt;br /&gt;            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;&lt;br /&gt;            Editor ed = doc.Editor;&lt;br /&gt;            bool GONOGO = true;&lt;br /&gt;            DataSet CntrlDS;&lt;br /&gt;            DataSet ToDoDS;&lt;br /&gt;            byte[] RtnVal = null;&lt;br /&gt;            if (this.DataBridgeForm.SuspenseQ.Count &gt; 0)&lt;br /&gt;            {&lt;br /&gt;                while (GONOGO &amp;&amp; this.DataBridgeForm.SuspenseQ.Count &gt; 0)&lt;br /&gt;                {&lt;br /&gt;                    object o = DataBridgeForm.SuspenseQ.Dequeue();&lt;br /&gt;                    try&lt;br /&gt;                    {&lt;br /&gt;                        CntrlDS = NPC.ExtractSerializedDataSet((byte[])o);&lt;br /&gt;                        if (CntrlDS != null)&lt;br /&gt;                        {&lt;br /&gt;                            if (NPC.HasPayLoad(ref CntrlDS))&lt;br /&gt;                            {&lt;br /&gt;                                ToDoDS = NPC.ExtractNPCTablePayLoad(ref CntrlDS);&lt;br /&gt;                                if (ToDoDS != null)&lt;br /&gt;                                {&lt;br /&gt;                                    RtnVal = ProcessRequest(ref CntrlDS, ref ToDoDS);&lt;br /&gt;                                }&lt;br /&gt;                            }&lt;br /&gt;                        }&lt;br /&gt;                        if (RtnVal != null)&lt;br /&gt;                            DataBridgeForm.ProcessQ.Enqueue(RtnVal);&lt;br /&gt;                        OnCompletedTask(this);&lt;br /&gt;                        RtnVal = null;&lt;br /&gt;                    }&lt;br /&gt;                    catch (System.Exception _Ex)&lt;br /&gt;                    {&lt;br /&gt;                        ed.WriteMessage("ERROR: " + _Ex.Message + "\r\n");&lt;br /&gt;                    }&lt;br /&gt;                } // end while GONOGO&lt;br /&gt;            }// if count in queue&lt;br /&gt;        }// OnReceivedQueueEntry&lt;br /&gt;}//eoc WRKR&lt;br /&gt;} // eons &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-652122425106956662?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=38be9ce4b292372c&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/652122425106956662/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2008/10/inter-process-communication-ipc-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/652122425106956662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/652122425106956662'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2008/10/inter-process-communication-ipc-with.html' title='Inter-Process Communication (IPC) with Autodesk Map3d'/><author><name>Dennis Jonio</name><uri>http://www.blogger.com/profile/14478827118325682041</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_tM5lW6vfyRw/SQcFVdSFXyI/AAAAAAAAAAM/6wBZFaJoVFU/s72-c/vis_aid00.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-3172420941228207668</id><published>2008-10-23T11:46:00.028+02:00</published><updated>2009-02-04T16:37:26.110+01:00</updated><title type='text'>Harvesting Autodesk DWG Entities</title><content type='html'>Author: Jonio, Dennis&lt;br /&gt;&lt;br /&gt;This kicks off a series of articles on building SDO_GEOMETRY types from DWG entities. By series end you should have at least one working NETLOADable module for a template. I do not pretend that this is THE solution. Since this was completed, I have, of course, realized better ways to do some things and I am sure you will be able to find more. I strongly recommend that you look over the Oracle OTN forums in particular .NET and Spatial. The heart and soul of these UDT’s came from there. Another indispensable forum is the Autodesk Discussion Groups. Their .NET forum is also indispensable.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Oracle SDO_GEOMETRY and a few others as User Defined Types (UDT’s)&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;Included below are a couple projects NetSdoGeometry and NetSdoDimArray. These are the fundamental classes and I have posted these in the past. However since that time I have added an &lt;span style="font-family:courier new;"&gt;AsText&lt;/span&gt; property and the &lt;span style="font-family:courier new;"&gt;ToString()&lt;/span&gt; method. It became necessary to actually visualize the objects during development. I must also point out that SDO_GEOMETRY is now marked as &lt;span style="font-family:courier new;"&gt;[Serializable]&lt;/span&gt;. You will see later on that this allows for the inclusion of this type into a native .NET serializable dataset. I have included a fair number of non-essential members and methods. They are for convenience so the purist may wish to strip them.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://tf-net.googlecode.com/files/NetSdoGeometry.zip"&gt;http://tf-net.googlecode.com/files/NetSdoGeometry.zip&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://tf-net.googlecode.com/files/NetSdoDimArray.zip"&gt;http://tf-net.googlecode.com/files/NetSdoDimArray.zip&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;Triplets and Triplet Management&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In order to make any sense of this article you will have to have a copy of Oracle’s SDO_GEOMETRY specification and my implementation of the class NetSdoGeometry.sdogeometry.&lt;br /&gt;&lt;br /&gt;Let me clarify, in general terms, what this implementation does and does not do in regards the specification&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Is Limited to two(2) dimensional geometries. Points, lines, surfaces(polygons)&lt;/li&gt;&lt;li&gt;Does not include “compound-type” geometries&lt;/li&gt;&lt;li&gt;Does include support for curves/arcs&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;After reviewing the spec you will realize it is all about “triplets”. The SDO_DIM_ELEM_ARRAY is of course a 1-&gt; n series of 3 element integers groups. OFFSET - ETYPE -INTERPRETATION as the named components.&lt;/p&gt;&lt;p&gt;The manipulation of the ordinates array I found to be rather trivial both in terms of composition and decomposition. It is nothing more than that a left to right series of numbers.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;“Triple Management” becomes the focus. Since I was learning the spec and writing code to it as I went along, the first class I created was, of course, “Triplet”. This class helped me visualize and understand the key elements of the specification. It is nothing more than codifying the obvious. The only oddity is my use of a GUID to track external or internal rings. The idea here will be explained later. In most cases a triplet acts as a kind’a sort’a header. A header that explains the ordinate array that is part of the SDO_GEOMETRY class. It would be just that simple if all one wished to do was work with linestrings. It is the support for curves/arcs that really adds a level of complexity by using a series of triplets to denote the transitions from line to arc, arc to line, etc.&lt;br /&gt;&lt;br /&gt;Class “Pts” is a simple container for holding the ordinates. Of note here is the BulgeValue member. This acts as the placeholder for the arc information gotten from, in my case Map3d.&lt;br /&gt;&lt;br /&gt;Finally class “TripletMgr” or Triplet Manager if you will. Before I discuss this class I will give you a chance to see how it is used. I do not use it for points and simple lines. Really unnecessary in those cases. This code decomposes as MPolygon into an sdogeometry. Frankly if you understand this one the rest is easy.&lt;br /&gt;&lt;/p&gt;Here is the basic idea: &lt;br /&gt;&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;  &lt;br /&gt;        public static sdogeometry PolygonGeometryFromMPolygon(MPolygon mpoly)&lt;br /&gt;        {&lt;br /&gt;            sdogeometry sdo = null;&lt;br /&gt;            Point2dCollection p2dColl = new Point2dCollection();&lt;br /&gt;            int hasBulgesCount;&lt;br /&gt;            int totalOrdinatesWritten = 0;                  // The total ordinates in the array&lt;br /&gt;            int totalSubElementCount = 0;                   // Just the total of sub-elements&lt;br /&gt;            int OWNERSHIP = 1;                              // Manage the OFFSET for a triplet &lt;br /&gt;            LoopDirection loopdirection;&lt;br /&gt;&lt;br /&gt;            TripletMgr MasterTripletMgr = new TripletMgr();&lt;br /&gt;            int loops = mpoly.NumMPolygonLoops;&lt;br /&gt;            for (int i = 0; i &lt; loops; i++)&lt;br /&gt;            {&lt;br /&gt;                // Gather up points and bulges for this loop&lt;br /&gt;                MPolygonLoop mPolygonLoop = mpoly.GetMPolygonLoopAt(i);&lt;br /&gt;                loopdirection = mpoly.GetLoopDirection(i);&lt;br /&gt;                hasBulgesCount = 0;&lt;br /&gt;                // Remove duplicate verticies&lt;br /&gt;                for (int d = 1; d &lt; mPolygonLoop.Count - 1; d++)&lt;br /&gt;                {&lt;br /&gt;                    if (mPolygonLoop[d].Vertex.IsEqualTo(mPolygonLoop[d + 1].Vertex))&lt;br /&gt;                    {&lt;br /&gt;                        mPolygonLoop.RemoveAt(d + 1);&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                //&lt;br /&gt;                Point2d[] pts = new Point2d[mPolygonLoop.Count];&lt;br /&gt;                double[] blgs = new double[mPolygonLoop.Count];&lt;br /&gt;                for (int z = 0; z &lt; mPolygonLoop.Count; z++)&lt;br /&gt;                {&lt;br /&gt;                    if (z == mPolygonLoop.Count - 1)&lt;br /&gt;                    {&lt;br /&gt;                        pts[z] = pts[0];&lt;br /&gt;                    }&lt;br /&gt;                    else&lt;br /&gt;                    {&lt;br /&gt;                        double X = Math.Round(mPolygonLoop[z].Vertex.X, 10, MidpointRounding.AwayFromZero);&lt;br /&gt;                        double Y = Math.Round(mPolygonLoop[z].Vertex.Y, 10, MidpointRounding.AwayFromZero);&lt;br /&gt;                        pts[z] = new Point2d(X, Y);&lt;br /&gt;                    }&lt;br /&gt;                    blgs[z] = mPolygonLoop[z].Bulge;&lt;br /&gt;                    if (blgs[z] != 0.0)&lt;br /&gt;                        hasBulgesCount = hasBulgesCount + 1;&lt;br /&gt;                }&lt;br /&gt;                // dej 2008/12/17&lt;br /&gt;                // Some fixup for starting and/or ending with an arc in that the bulges get duplicated&lt;br /&gt;                // along with the vertices. This also seems to be a bigger issue with "Inner" vs "Outer"&lt;br /&gt;                // loops. Obviously if we have a series of arcs they won't have dup values anyway.&lt;br /&gt;                // We must not decrement hasBulgesCount!!!&lt;br /&gt;                if (blgs[0] == blgs[mPolygonLoop.Count - 1])&lt;br /&gt;                    blgs[mPolygonLoop.Count - 1] = 0.0;&lt;br /&gt;&lt;br /&gt;                //&lt;br /&gt;                // Finished getting all the ordinates and bulges for this loop&lt;br /&gt;                //&lt;br /&gt;                // Just a dummy triplet to work with and begin the process of formulation&lt;br /&gt;                // Each loop needs its own header triplet.&lt;br /&gt;                // Establish the ETYPE and the OWNERSHIP(OFFSET) marker for this header&lt;br /&gt;                // and its INTERPRETATION&lt;br /&gt;                int headerOffset = (i == 0) ? 1 : OWNERSHIP;&lt;br /&gt;                Triplet dummy_headerTriplet = new Triplet(new int[] { headerOffset, 0, 0 });&lt;br /&gt;                if (hasBulgesCount == 0)&lt;br /&gt;                    dummy_headerTriplet.INTERPRETATION = 1; // all "lines"&lt;br /&gt;                else if (hasBulgesCount == pts.Length)&lt;br /&gt;                    dummy_headerTriplet.INTERPRETATION = 2; // all "arcs"&lt;br /&gt;                // if it is not a 1 or 2 we have to fill the INTERPRETATION value in later&lt;br /&gt;                // because it contains the number of subelements&lt;br /&gt;                if (loopdirection == LoopDirection.Exterior)&lt;br /&gt;                {&lt;br /&gt;                    // It is an exterior&lt;br /&gt;                    if (dummy_headerTriplet.INTERPRETATION == 1 || dummy_headerTriplet.INTERPRETATION == 2)&lt;br /&gt;                    {&lt;br /&gt;                        dummy_headerTriplet.ETYPE = 1003;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                else&lt;br /&gt;                {&lt;br /&gt;                    // It is an interior&lt;br /&gt;                    if (dummy_headerTriplet.INTERPRETATION == 1 || dummy_headerTriplet.INTERPRETATION == 2)&lt;br /&gt;                    {&lt;br /&gt;                        dummy_headerTriplet.ETYPE = 2003;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                // We have not set the etype yet so it must be a 1005 0R 2005 - compound polygon&lt;br /&gt;                // dej 2008/12/17 if (dummy_headerTriplet.ETYPE == 0)&lt;br /&gt;                if (dummy_headerTriplet.ETYPE == 0 || hasBulgesCount &gt; 0)&lt;br /&gt;                {&lt;br /&gt;                    if (loopdirection == LoopDirection.Exterior)&lt;br /&gt;                        dummy_headerTriplet.ETYPE = 1005;&lt;br /&gt;                    else&lt;br /&gt;                        dummy_headerTriplet.ETYPE = 2005;&lt;br /&gt;                }&lt;br /&gt;                //&lt;br /&gt;                // Every time we make a transition from/to a curve/line we will make up a triplet&lt;br /&gt;                //&lt;br /&gt;                // We new-up a triplet mgr for these subelements within this loop&lt;br /&gt;                // We do know that the etype MUST be a 2 - line or arc&lt;br /&gt;                //&lt;br /&gt;                TripletMgr tmgr = new TripletMgr();&lt;br /&gt;                Triplet nxtTriplet = null;&lt;br /&gt;                int currentINTERPRETATION = 0;&lt;br /&gt;                int lastwrittenINTERPRETATION = 0;&lt;br /&gt;                Point2d somePointOnArc;&lt;br /&gt;                Point2d arc_endpoint;&lt;br /&gt;                for (int j = 0; j &lt; mPolygonLoop.Count; j++)&lt;br /&gt;                {&lt;br /&gt;                    double theBulge = blgs[j];&lt;br /&gt;                    //Test the bulge&lt;br /&gt;                    if (theBulge != 0.0)&lt;br /&gt;                    {&lt;br /&gt;                        // Look ahead to get the endpoint for the arc&lt;br /&gt;                        if (j == (mPolygonLoop.Count - 1))&lt;br /&gt;                            arc_endpoint = pts[0];&lt;br /&gt;                        else&lt;br /&gt;                            arc_endpoint = pts[j + 1];&lt;br /&gt;&lt;br /&gt;                        CircularArc2d ca2d = new CircularArc2d(pts[j], arc_endpoint, theBulge, false);&lt;br /&gt;                        //&lt;br /&gt;                        // Get the center point on the arc ....&lt;br /&gt;                        // As an alternative:/ Point2d[] somePointSOnArc = ca2d.GetSamplePoints(3);&lt;br /&gt;                        // The somePointSOnArc[1] element will have the centerpoint on the arc&lt;br /&gt;                        //&lt;br /&gt;                        Interval interval_of_arc = ca2d.GetInterval();&lt;br /&gt;                        somePointOnArc = ca2d.EvaluatePoint(interval_of_arc.Element / 2);&lt;br /&gt;                        currentINTERPRETATION = 2;&lt;br /&gt;                    }&lt;br /&gt;                    else&lt;br /&gt;                    {&lt;br /&gt;                        currentINTERPRETATION = 1;&lt;br /&gt;                    }&lt;br /&gt;                    // This only happens once per loop/ring because nxtTriplet is no longer null&lt;br /&gt;                    // We use this to start off the tracking transitions from-to curves/lines&lt;br /&gt;                    if (nxtTriplet == null)&lt;br /&gt;                    {&lt;br /&gt;                        int elementOffset = (i == 0) ? 1 : OWNERSHIP;&lt;br /&gt;                        nxtTriplet = new Triplet(new int[] { elementOffset, 2, currentINTERPRETATION });&lt;br /&gt;                        lastwrittenINTERPRETATION = currentINTERPRETATION;&lt;br /&gt;                    }&lt;br /&gt;                    // Now collect the points and if we have a bulge add the midpoint only &lt;br /&gt;                    // and not the endpoint that will be next&lt;br /&gt;                    p2dColl.Add(pts[j]);&lt;br /&gt;                    totalOrdinatesWritten = totalOrdinatesWritten + 2;&lt;br /&gt;                    OWNERSHIP = OWNERSHIP + 2;&lt;br /&gt;                    if (theBulge != 0.0)&lt;br /&gt;                    {&lt;br /&gt;                        p2dColl.Add(new Point2d(somePointOnArc.ToArray()));&lt;br /&gt;                        totalOrdinatesWritten = totalOrdinatesWritten + 2;&lt;br /&gt;                        OWNERSHIP = OWNERSHIP + 2;&lt;br /&gt;                        // Oracle must be made happy.&lt;br /&gt;                        // OK this is really tricky ... the next item may or may not have a bulge&lt;br /&gt;                        // if the next item is at the end and it has a bulge this is a circle!&lt;br /&gt;                        // If it does not it is a line and we must loop back up so we make the proper&lt;br /&gt;                        // switch on interp and get the OWNERSHIP value correct. Otherwise&lt;br /&gt;                        // our OWNERSHIP value will be off by 2&lt;br /&gt;                        // &lt;br /&gt;                        if ((j + 1) == (mPolygonLoop.Count - 1))&lt;br /&gt;                        {&lt;br /&gt;                            if (blgs[j + 1] != 0.0)&lt;br /&gt;                            {&lt;br /&gt;                                p2dColl.Add(pts[j + 1]);&lt;br /&gt;                                totalOrdinatesWritten = totalOrdinatesWritten + 2;&lt;br /&gt;                                OWNERSHIP = OWNERSHIP + 2;&lt;br /&gt;                                j = j + 1;&lt;br /&gt;                            }&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;                    //&lt;br /&gt;                    // Now we construct an additional triplet in the event we have changed INTERPRETATION&lt;br /&gt;                    //&lt;br /&gt;                    if (currentINTERPRETATION != lastwrittenINTERPRETATION)&lt;br /&gt;                    {&lt;br /&gt;                        tmgr.TripletList.Add(nxtTriplet);&lt;br /&gt;                        totalSubElementCount++;&lt;br /&gt;                        // &lt;br /&gt;                        // If I am transitioning to an arc/curve my ownership actually started&lt;br /&gt;                        // 4 ordinates ago or 2 ordinates ago in the case of a line&lt;br /&gt;                        //&lt;br /&gt;                        int elementOffset = (currentINTERPRETATION == 2) ? (OWNERSHIP - 4) : OWNERSHIP - 2;&lt;br /&gt;                        nxtTriplet = new Triplet(new int[] { elementOffset, 2, currentINTERPRETATION });&lt;br /&gt;                        lastwrittenINTERPRETATION = currentINTERPRETATION;&lt;br /&gt;                    }&lt;br /&gt;                }   // end of for-loop on vertex count ... finished with one of the rings.&lt;br /&gt;                //&lt;br /&gt;                // Add this last triplet no matter what&lt;br /&gt;                //&lt;br /&gt;                tmgr.TripletList.Add(nxtTriplet);&lt;br /&gt;                totalSubElementCount++;&lt;br /&gt;                //&lt;br /&gt;                // If we are a 1005 or a 2005 we must fix-up the header triplet to reflect&lt;br /&gt;                // the total number of triplets(subelements) that are present. In this case it&lt;br /&gt;                // gets stuffed into the INTERP position.&lt;br /&gt;                // In the end the Master will hold the entire polygon&lt;br /&gt;                //&lt;br /&gt;                if (tmgr.TripletCount &gt; 1)&lt;br /&gt;                {&lt;br /&gt;                    dummy_headerTriplet.INTERPRETATION = totalSubElementCount;&lt;br /&gt;                    MasterTripletMgr.TripletList.Add(dummy_headerTriplet);&lt;br /&gt;                    for (int x = 0; x &lt; tmgr.TripletCount; x++)&lt;br /&gt;                    {&lt;br /&gt;                        MasterTripletMgr.TripletList.Add(tmgr.TripletList[x]);&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                //&lt;br /&gt;                // If we are a 1003 or a 2003&lt;br /&gt;                //&lt;br /&gt;                if (tmgr.TripletCount == 1)&lt;br /&gt;                {&lt;br /&gt;                    MasterTripletMgr.TripletList.Add(dummy_headerTriplet);&lt;br /&gt;                }&lt;br /&gt;                // Set for next ring ...&lt;br /&gt;                totalSubElementCount = 0;&lt;br /&gt;            }// for each loop in the mpolygon&lt;br /&gt;            //&lt;br /&gt;            // We should have the geometry for the entire MPolygon described&lt;br /&gt;            // Construct the sdo_geometry object&lt;br /&gt;            //&lt;br /&gt;            sdo = new sdogeometry();&lt;br /&gt;            sdo.Dimensionality = (int)sdogeometryTypes.DIMENSION.DIM2D;&lt;br /&gt;            sdo.ElemArrayOfInts = MasterTripletMgr.ElementInfoToArray;&lt;br /&gt;            double[] rtnval = new double[p2dColl.Count * 2];&lt;br /&gt;            for (int w = 0, cnt = 0; w &lt; p2dColl.Count; w++)&lt;br /&gt;            {&lt;br /&gt;                rtnval[cnt++] = p2dColl[w].X; rtnval[cnt++] = p2dColl[w].Y;&lt;br /&gt;            }&lt;br /&gt;            sdo.OrdinatesArrayOfDoubles = rtnval;&lt;br /&gt;            sdo.GeometryType = (int)sdogeometryTypes.GTYPE.POLYGON;&lt;br /&gt;            sdo.PropertiesToGTYPE();&lt;br /&gt;            return sdo;&lt;br /&gt;        }&lt;br /&gt; &lt;/pre&gt;&lt;br /&gt;The method SetPts is the workhorse. Once again it is the management of the triplets. The concept of “ownership” can from &lt;em&gt;&lt;strong&gt;Pro Oracle Spatial for Oracle Database 11g&lt;/strong&gt;&lt;/em&gt;, by Kothuri, Godfrind, Beinat. This really helped me put some of the pieces together. I recommend it highly.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Source code (C#) available for download at:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://tf-net.googlecode.com/files/Triplet_Pts_TripletMgr.zip"&gt;http://tf-net.googlecode.com/files/Triplet_Pts_TripletMgr.zip&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-3172420941228207668?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/3172420941228207668/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2008/10/harvesting-autodesk-dwg-entities.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/3172420941228207668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/3172420941228207668'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2008/10/harvesting-autodesk-dwg-entities.html' title='Harvesting Autodesk DWG Entities'/><author><name>Maksim Sestic</name><uri>http://www.blogger.com/profile/11155932635442483931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-7687999894267364329</id><published>2008-08-02T14:09:00.014+02:00</published><updated>2008-10-25T13:11:01.390+02:00</updated><title type='text'>Working with Oracle UDT’s with AutoCAD Map 3D</title><content type='html'>Author: Jonio, Dennis&lt;br /&gt;&lt;br /&gt;Within this series of articles I have pretty well illustrated Oracle’s ODP.NET working in "harmony" with Autodesk’s Map3d 2008. Also note that I have used Oracle XE throughout. The functionality Locator brings is certainly more than enough to build a reasonable GIS data store. I have not spent any time in outlining any of the other Oracle stored procedures like &lt;span style="font-family:courier new;"&gt;SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT()&lt;/span&gt; these are all well documented across the internet. As I have said before, FDO is the way to go. But you still need to get that geometry built somewhere and put into a data store. "Map Export to FDO" is obviously a work in progress but hopefully will become a useful tool down the road.&lt;br /&gt;&lt;br /&gt;&lt;a id="Lessons_Learned"&gt;&lt;strong&gt;Lessons Learned&lt;/strong&gt;&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Always turn Connection Pooling OFF when working with UDT’s. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Do NOT use the App.config method for UDT discovery that is described in the ODP.NET documentation. This does no work in all cases. It seems nested classes are not always resolved. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Since your UDT class assembly(s) will be referenced from, in the default case: "C:\Program Files\AutoCAD Map 3D 2008", be careful of your naming convention.&lt;/li&gt;&lt;/ul&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;using Autodesk.AutoCAD.ApplicationServices;&lt;br /&gt;using Autodesk.AutoCAD.DatabaseServices;&lt;br /&gt;using Autodesk.AutoCAD.EditorInput;&lt;br /&gt;using Autodesk.AutoCAD.Runtime;&lt;br /&gt;using Autodesk.AutoCAD.Geometry;&lt;br /&gt;using System.Reflection;&lt;br /&gt;using System.Collections;&lt;br /&gt;using System.IO;&lt;br /&gt;using System.Text;&lt;br /&gt;using System.Data;&lt;br /&gt;using System;&lt;br /&gt;using Oracle.DataAccess.Client;&lt;br /&gt;using Oracle.DataAccess.Types;&lt;br /&gt;using NetSdoGeometry;&lt;br /&gt;&lt;br /&gt;[assembly: ExtensionApplication(typeof(YOURCLEVERAPPNAME.Initialization))]&lt;br /&gt;[assembly: CommandClass(typeof(YOURCLEVERAPPNAME.YOURCLEVERAPPNAME))]&lt;br /&gt;namespace YOURCLEVERAPPNAME&lt;br /&gt;{&lt;br /&gt;    public class YOURCLEVERAPPNAME&lt;br /&gt;    {&lt;br /&gt;        public static string LocationOfDll;&lt;br /&gt;        public static string forReadDwgFileInit = "forReadDwgFileInit.dwg";&lt;br /&gt;&lt;br /&gt;        public YOURCLEVERAPPNAME()&lt;br /&gt;        {&lt;br /&gt;            Assembly callee = Assembly.GetExecutingAssembly();&lt;br /&gt;            LocationOfDll = Path.GetDirectoryName(callee.Location);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;       [CommandMethod("YOURCLEVERAPPNAME")]&lt;br /&gt;        public void mycleverapp()&lt;br /&gt;        {&lt;br /&gt;            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;&lt;br /&gt;            Editor ed = doc.Editor;&lt;br /&gt;&lt;br /&gt;            //&lt;br /&gt;            // Must do this before any Oracle.DataAccess method calls.&lt;br /&gt;            // If you start getting “First chance exceptions” in VS you know things are hosed.&lt;br /&gt;            //&lt;br /&gt;            Database Xdb = new Database(false, false);&lt;br /&gt;            Xdb.ReadDwgFile(LocationOfDll + "\\" + forReadDwgFileInit,FileShare.ReadWrite, false, null);&lt;br /&gt;            Xdb.Dispose();&lt;br /&gt;&lt;br /&gt;            //&lt;br /&gt;            // I do not understand but I needed this HERE to resolve sdo_geometry&lt;br /&gt;            //&lt;br /&gt;            sdogeometry NEED_HERE_TO_RESOLVE_sdogeometry = new sdogeometry();&lt;br /&gt;            using (DocumentLock docLock = doc.LockDocument())&lt;br /&gt;            {&lt;br /&gt;                  // do whatever needs doing&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }//eoc YOURCLEVERAPPNAME&lt;br /&gt;&lt;br /&gt;    public class Initialization : Autodesk.AutoCAD.Runtime.IExtensionApplication&lt;br /&gt;    {&lt;br /&gt;        public void Initialize()&lt;br /&gt;        {&lt;br /&gt;            Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;&lt;br /&gt;            Assembly caller = Assembly.GetCallingAssembly();&lt;br /&gt;            Assembly callee = Assembly.GetExecutingAssembly();&lt;br /&gt;            string callername = caller.FullName;&lt;br /&gt;            string calleename = callee.FullName;&lt;br /&gt;            ed.WriteMessage("Loader: " + callername + " initialize " + calleename);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void Terminate()&lt;br /&gt;        {&lt;br /&gt;            Assembly callee = Assembly.GetExecutingAssembly();&lt;br /&gt;            string calleename = callee.FullName;&lt;br /&gt;            Console.WriteLine("Cleaning up..." + calleename);&lt;br /&gt;        }&lt;br /&gt;    }//eoc Initialize&lt;br /&gt;}//eons&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-7687999894267364329?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/7687999894267364329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2008/08/working-with-oracle-udts-with-autocad.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/7687999894267364329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/7687999894267364329'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2008/08/working-with-oracle-udts-with-autocad.html' title='Working with Oracle UDT’s with AutoCAD Map 3D'/><author><name>Maksim Sestic</name><uri>http://www.blogger.com/profile/11155932635442483931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-8600613883740457036</id><published>2008-05-30T13:57:00.004+02:00</published><updated>2008-10-25T14:07:15.991+02:00</updated><title type='text'>ODP.NET 11g, Oracle XE 10.2, ObjectARX.NET, Autodesk Map3d 2008, OSGeo FDO 3.2</title><content type='html'>Author: Jonio, Dennis&lt;br /&gt;&lt;br /&gt;Just some basics to let you know my current bias. I do believe that FDO is the way of the way to go. Without a doubt this is the correct track to be on. Just like everything else however, it has a way to go to get to maturity. I do not like the Autodesk FDO provider for Oracle. IMHO, Haris Kurtagic’s &lt;a href="http://www.sl-king.com/fdooracle/fdooracle.html"&gt;King.Oracle Provider&lt;/a&gt; is the way to go. Of course his, &lt;a href="http://www.sl-king.com/fdo2fdo/fdo2fdo.html"&gt;FDO2FDO&lt;/a&gt; is essential and an excellent piece of work.&lt;br /&gt;&lt;br /&gt;That being said I really did not wish to deal with all the "weight" that FDO brings to every application. So I thought I would code up an application that moved DWG geometry to an Oracle table. It seemed to me to be a fairly straightforward task since I had put together that UDT for MDSYS.SDO_GEOMETRY. I always wondered why I had not seen some code examples of doing this. Well folks, now I know...&lt;br /&gt;&lt;br /&gt;ODP does not play well with Map3d. For those of you who do ObjectARX.NET applications there are significant problems in heap management between ODP and Map3d. The basic premise of this app is to open a DWG as an "aside" using &lt;span style="font-family:courier new;"&gt;ReadDwgFile()&lt;/span&gt;, iterate the geometry, convert it to the correct format and insert it into the table. Let me "cut to the chase" on this one. It ended up that I had to "load" a DWG before any call was made to any ODP.NET classes. (In all fairness to Autodesk they are very clear in that they do not support these foreign database access methods within there architecture.) Once this is done there is no difficulty. I am able to iterate through a list of DWG’s and instantiate the database with &lt;span style="font-family:courier new;"&gt;ReadDwgFile()&lt;/span&gt; any number of times. At least in my case the acad.exe heap is now toast. For example, if after netloading and executing my app I attempt to use FDO within Map 3D it will fail. Just restart Map 3D and all is fine.&lt;br /&gt;&lt;br /&gt;I had set up my sdogeometry UDT in a separate class being that I did not wish to duplicate the code across any number of applications. This is of course doable but I had a very frustrating time getting ODP.NET to "see" my UDT class within the Map3d environment. As the documentation reads, &lt;span style="font-family:courier new;"&gt;Oracle.Access.Client&lt;/span&gt; does a reflection on the executing assembly and looks for the &lt;span style="font-family:courier new;"&gt;OracleCustomTypeMappingAttribute&lt;/span&gt;. This works great if your UDT class is internal to your assembly. If you have an external class assembly the alternative is to set up an xml App.config file that Client will look for or add an entry to the machine.config. I never got this to work. I found that I had to actually instantiate an &lt;span style="font-family:courier new;"&gt;NetSdoGeometry.sdogeometry&lt;/span&gt; object within the &lt;span style="font-family:courier new;"&gt;[CommandMethod("????")]&lt;/span&gt; decorated method. Wow … NOT a big sacrifice but it did take me some time to come up with the correct timings.&lt;br /&gt;&lt;br /&gt;To do the conversions from Map3d I first used TF.NET to convert to a JTS IGeometry object and to Maksim’s credit this seems to work well. (I did, however, take the time to code up emulating a circle as a linestring.) To do the conversion to sdogeometry I used Oracle’s JGeometry object. Remember I am working with Oracle XE 10.2 and it does not come with the builtin JVM so WKB/WKT are there but return nothing. I choose not to use the monoGIS distribution and did the IKVM byte code conversions myself using the most current JGeometry version I could find. Since I was only interested in the WKB/WKT methods I was not too concerned with the warnings coming out of IKVM. I forget the compile order but I needed these 4: sdoapi, sdoutl, xmlparserv2 and ojdbc5.&lt;br /&gt;&lt;br /&gt;At this point a have a fully functional application. Not the fastest piece of code I have done but I certainly do exercise TF.NET. The next step will be to code up the load of the sdogeometry objects directly. But, I am in no hurry. Computer cycles are a lot cheaper than my time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-8600613883740457036?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/8600613883740457036/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2008/05/odpnet-11g-oracle-xe-102-objectarxnet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/8600613883740457036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/8600613883740457036'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2008/05/odpnet-11g-oracle-xe-102-objectarxnet.html' title='ODP.NET 11g, Oracle XE 10.2, ObjectARX.NET, Autodesk Map3d 2008, OSGeo FDO 3.2'/><author><name>Maksim Sestic</name><uri>http://www.blogger.com/profile/11155932635442483931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-7340513157982882275</id><published>2008-05-30T12:44:00.009+02:00</published><updated>2008-10-30T15:16:16.123+01:00</updated><title type='text'>Oracle's SDO_DIM_ARRAY as UDT and utilizing SDO_MIGRATE.TO_CURRENT as stored procedure</title><content type='html'>Author: Jonio, Dennis&lt;br /&gt;&lt;br /&gt;Utilizing Oracle’s latest ODP for .NET the following is one implementation of the &lt;span style="font-family:courier new;"&gt;SDO_DIM_ARRAY&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;SDO_DIM_ELEMENT&lt;/span&gt; type(s) as a .NET class.&lt;br /&gt;&lt;br /&gt;This one is easy to explain. I needed to use &lt;span style="font-family:courier new;"&gt;SDO_MIGRATE.TO_CURRENT&lt;/span&gt; to fix some &lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=683019&amp;amp;tstart=15"&gt;ORA-13367: wrong orientation for interior/exterior rings errors&lt;/a&gt;. So I needed &lt;span style="font-family:courier new;"&gt;SDO_DIM_ARRAY&lt;/span&gt; and thusly &lt;span style="font-family:courier new;"&gt;SDO_DIM_ELEMENT&lt;/span&gt; because &lt;span style="font-family:courier new;"&gt;SDO_MIGRATE.TO_CURRENT&lt;/span&gt; requires a &lt;span style="font-family:courier new;"&gt;SDO_DIM_ARRAY&lt;/span&gt; as a parameter. I have included my method of utilizing &lt;span style="font-family:courier new;"&gt;SDO_MIGRATE.TO_CURRENT&lt;/span&gt; after the class definitions.&lt;br /&gt;&lt;br /&gt;Source code (C#):&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections;&lt;br /&gt;using System.Text;&lt;br /&gt;using Oracle.DataAccess.Client;&lt;br /&gt;using Oracle.DataAccess.Types;&lt;br /&gt;&lt;br /&gt;namespace NetSdoDimArray&lt;br /&gt;{&lt;br /&gt;    /// &lt;summary&gt;&lt;br /&gt;    /// ////////////////////////////////////&lt;br /&gt;    /// sdodimarray&lt;br /&gt;    /// ////////////////////////////////////&lt;br /&gt;    /// &lt;/summary&gt;&lt;br /&gt;    public class sdodimarray : IOracleCustomType, INullable&lt;br /&gt;    {&lt;br /&gt;        [OracleObjectMapping(0)]&lt;br /&gt;        public sdodimelement[] _dimelements;&lt;br /&gt;        private bool m_bIsNull;&lt;br /&gt;&lt;br /&gt;        public bool IsNull&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                return m_bIsNull;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public sdodimelement[] DimElements&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                return _dimelements;&lt;br /&gt;            }&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                _dimelements = value;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public static sdodimarray Null&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                sdodimarray obj = new sdodimarray();&lt;br /&gt;                obj.m_bIsNull = true;&lt;br /&gt;                return obj;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public override string ToString()&lt;br /&gt;        {&lt;br /&gt;            if (m_bIsNull)&lt;br /&gt;                return "sdodimarray.Null";&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                StringBuilder sb = new StringBuilder();&lt;br /&gt;                foreach (sdodimelement i in _dimelements)&lt;br /&gt;                {&lt;br /&gt;                    sb.Append("sdodimelement(");&lt;br /&gt;                    sb.Append(i._dimname + "=");&lt;br /&gt;                    sb.Append(string.Format("{0:0.#####}", i._lb));&lt;br /&gt;                    sb.Append(",");&lt;br /&gt;                    sb.Append(string.Format("{0:0.#####}", i._ub));&lt;br /&gt;                    sb.Append(",Tol=");&lt;br /&gt;                    sb.Append(i._tolerance.ToString());&lt;br /&gt;                    sb.Append(")");&lt;br /&gt;                }&lt;br /&gt;                return sb.ToString();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void ToCustomObject(OracleConnection con, IntPtr pUdt)&lt;br /&gt;        {&lt;br /&gt;            _dimelements = (sdodimelement[])OracleUdt.GetValue(con, pUdt, 0);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void FromCustomObject(OracleConnection con, IntPtr pUdt)&lt;br /&gt;        {&lt;br /&gt;            OracleUdt.SetValue(con, pUdt, 0, _dimelements);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [OracleCustomTypeMapping("MDSYS.SDO_DIM_ARRAY")]&lt;br /&gt;    public class sdodimarrayFactory : IOracleArrayTypeFactory, IOracleCustomTypeFactory&lt;br /&gt;    {&lt;br /&gt;        // IOracleCustomTypeFactory Inteface&lt;br /&gt;        public IOracleCustomType CreateObject()&lt;br /&gt;        {&lt;br /&gt;            return new sdodimarray();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // IOracleArrayTypeFactory.CreateArray Inteface&lt;br /&gt;        public Array CreateArray(int numElems)&lt;br /&gt;        {&lt;br /&gt;            return new sdodimelement[numElems];&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // IOracleArrayTypeFactory.CreateStatusArray&lt;br /&gt;        public Array CreateStatusArray(int numElems)&lt;br /&gt;        {&lt;br /&gt;            // An OracleUdtStatus[] is not required to store null status information&lt;br /&gt;            // if there is no NULL attribute data in the element array&lt;br /&gt;            return null;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /// &lt;summary&gt;&lt;br /&gt;    /// ////////////////////////////////////&lt;br /&gt;    /// sdodimelement&lt;br /&gt;    /// ////////////////////////////////////&lt;br /&gt;    /// &lt;/summary&gt;&lt;br /&gt;    public class sdodimelement : IOracleCustomType, INullable&lt;br /&gt;    {&lt;br /&gt;        [OracleObjectMapping(0)]&lt;br /&gt;        public string _dimname;&lt;br /&gt;&lt;br /&gt;        [OracleObjectMapping(1)]&lt;br /&gt;        public double _lb;&lt;br /&gt;&lt;br /&gt;        [OracleObjectMapping(2)]&lt;br /&gt;        public double _ub;&lt;br /&gt;&lt;br /&gt;        [OracleObjectMapping(3)]&lt;br /&gt;        public double _tolerance;&lt;br /&gt;&lt;br /&gt;        private bool m_bIsNull;&lt;br /&gt;&lt;br /&gt;        public bool IsNull&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                return m_bIsNull;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public static sdodimelement Null&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                sdodimelement obj = new sdodimelement();&lt;br /&gt;                obj.m_bIsNull = true;&lt;br /&gt;                return obj;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public override string ToString()&lt;br /&gt;        {&lt;br /&gt;            if (m_bIsNull)&lt;br /&gt;                return "sdodimelement.Null";&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                StringBuilder sb = new StringBuilder();&lt;br /&gt;                sb.Append("sdodimelement(");&lt;br /&gt;                sb.Append(_dimname + "=");&lt;br /&gt;                sb.Append(string.Format("{0:0.#####}", _lb));&lt;br /&gt;                sb.Append(",");&lt;br /&gt;                sb.Append(string.Format("{0:0.#####}", _ub));&lt;br /&gt;                sb.Append(",Tol=");&lt;br /&gt;                sb.Append(_tolerance.ToString());&lt;br /&gt;                sb.Append(")");&lt;br /&gt;                return sb.ToString();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void ToCustomObject(OracleConnection con, IntPtr pUdt)&lt;br /&gt;        {&lt;br /&gt;            _dimname = (string)OracleUdt.GetValue(con, pUdt, 0);&lt;br /&gt;            _lb = (double)OracleUdt.GetValue(con, pUdt, 1);&lt;br /&gt;            _ub = (double)OracleUdt.GetValue(con, pUdt, 2);&lt;br /&gt;            _tolerance = (double)OracleUdt.GetValue(con, pUdt, 3);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void FromCustomObject(OracleConnection con, IntPtr pUdt)&lt;br /&gt;        {&lt;br /&gt;            OracleUdt.SetValue(con, pUdt, 0, _dimname);&lt;br /&gt;            OracleUdt.SetValue(con, pUdt, 1, _lb);&lt;br /&gt;            OracleUdt.SetValue(con, pUdt, 2, _ub);&lt;br /&gt;            OracleUdt.SetValue(con, pUdt, 3, _tolerance);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [OracleCustomTypeMapping("MDSYS.SDO_DIM_ELEMENT")]&lt;br /&gt;    public class sdodimelementFactory : IOracleCustomTypeFactory&lt;br /&gt;    {&lt;br /&gt;        // IOracleCustomTypeFactory Inteface&lt;br /&gt;        public IOracleCustomType CreateObject()&lt;br /&gt;        {&lt;br /&gt;            sdodimelement sdodimelement = new sdodimelement();&lt;br /&gt;            return sdodimelement;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;As you see, it utilizes both sdogeometry and sdodimarray...&lt;br /&gt;&lt;pre class="c-sharp:collapse" name="code"&gt;&lt;br /&gt;public static sdogeometry MigrateToCurrentSP(string connectstring, sdogeometry _geoIn, sdodimarray _toleranceIn)&lt;br /&gt;        {&lt;br /&gt;            //ORA-13367:      wrong orientation for interior/exterior rings&lt;br /&gt;            sdogeometry rtnval = null;&lt;br /&gt;            using (OracleConnection conn = new OracleConnection(connectstring))&lt;br /&gt;            {&lt;br /&gt;                using (OracleCommand dbcmd = conn.CreateCommand())&lt;br /&gt;                {&lt;br /&gt;                    dbcmd.CommandType = CommandType.StoredProcedure;&lt;br /&gt;                    dbcmd.CommandText = "SDO_MIGRATE.TO_CURRENT";&lt;br /&gt;&lt;br /&gt;                    OracleParameter cParm1 = new OracleParameter();&lt;br /&gt;                    cParm1.ParameterName = "geometry";&lt;br /&gt;                    cParm1.OracleDbType = OracleDbType.Object;&lt;br /&gt;                    cParm1.Value = _geoIn;&lt;br /&gt;                    cParm1.UdtTypeName = "MDSYS.SDO_GEOMETRY";&lt;br /&gt;                    cParm1.Direction = ParameterDirection.Input;&lt;br /&gt;&lt;br /&gt;                    OracleParameter cParm2 = new OracleParameter();&lt;br /&gt;                    cParm2.ParameterName = "tolerance";&lt;br /&gt;                    cParm2.OracleDbType = OracleDbType.Object;&lt;br /&gt;                    cParm2.Value = _toleranceIn;&lt;br /&gt;                    cParm2.UdtTypeName = "MDSYS.SDO_DIM_ARRAY";&lt;br /&gt;                    cParm2.Direction = ParameterDirection.Input;&lt;br /&gt;&lt;br /&gt;                    OracleParameter cParm3 = new OracleParameter();&lt;br /&gt;                    cParm3.ParameterName = "RETURNVALUE";&lt;br /&gt;                    cParm3.OracleDbType = OracleDbType.Object;&lt;br /&gt;                    cParm3.UdtTypeName = "MDSYS.SDO_GEOMETRY";&lt;br /&gt;                    cParm3.Direction = ParameterDirection.ReturnValue;&lt;br /&gt;&lt;br /&gt;                    // Note the order&lt;br /&gt;                    dbcmd.Parameters.Add(cParm3);&lt;br /&gt;                    dbcmd.Parameters.Add(cParm1);&lt;br /&gt;                    dbcmd.Parameters.Add(cParm2);&lt;br /&gt;&lt;br /&gt;                    try&lt;br /&gt;                    {&lt;br /&gt;                        conn.Open();&lt;br /&gt;                        dbcmd.ExecuteNonQuery();&lt;br /&gt;                        rtnval = (sdogeometry)dbcmd.Parameters["RETURNVALUE"].Value;&lt;br /&gt;                    }&lt;br /&gt;                    catch (Exception _Ex)&lt;br /&gt;                    {&lt;br /&gt;                        throw (_Ex); // Actually rethrow&lt;br /&gt;                    }&lt;br /&gt;                    finally&lt;br /&gt;                    {&lt;br /&gt;                        if (conn != null &amp;amp;&amp;amp; conn.State == ConnectionState.Open)&lt;br /&gt;                        {&lt;br /&gt;                            conn.Close();&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;                }//using cmd&lt;br /&gt;            }//using conn&lt;br /&gt;&lt;br /&gt;            return rtnval;&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-7340513157982882275?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/7340513157982882275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2008/05/oracles-sdodimarray-as-udt-and.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/7340513157982882275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/7340513157982882275'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2008/05/oracles-sdodimarray-as-udt-and.html' title='Oracle&apos;s SDO_DIM_ARRAY as UDT and utilizing SDO_MIGRATE.TO_CURRENT as stored procedure'/><author><name>Maksim Sestic</name><uri>http://www.blogger.com/profile/11155932635442483931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-1680477411243443222</id><published>2007-01-13T12:04:00.008+01:00</published><updated>2008-11-04T12:41:38.124+01:00</updated><title type='text'>A note to contributors</title><content type='html'>Author: Sestic, Maksim&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Inserting Source Code Snippets&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Seems more complex than actually writing it :-) I embedded some tiny JavaScript source code parser in the blog head tag, here's how authors should use it to avoid article/code malformatting:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Write article body first (no source code yet) using &lt;strong&gt;&lt;span style="font-family:trebuchet ms;"&gt;Compose&lt;/span&gt;&lt;/strong&gt; tool, leaving blank paragraphs for future source code snippets&lt;/li&gt;&lt;li&gt;When you have your article fully formatted, hit the &lt;span style="font-family:trebuchet ms;"&gt;&lt;strong&gt;Save Now&lt;/strong&gt;&lt;/span&gt; button&lt;/li&gt;&lt;li&gt;Switch to &lt;strong&gt;&lt;span style="font-family:trebuchet ms;"&gt;Edit Html&lt;/span&gt;&lt;/strong&gt; tool. That's how article's underlying HTML looks like&lt;/li&gt;&lt;li&gt;Find the spot where you want your source code snippet inserted&lt;/li&gt;&lt;li&gt;Open actual source file (.cs) in Visual Studio, copy the source code (Ctrl+C)&lt;/li&gt;&lt;li&gt;Go back to article's HTML and paste (Ctrl+V) code snippet enclosing it with &lt;span style="font-family:courier new;"&gt;&amp;lt;pre&amp;gt;&amp;lt;\pre&amp;gt;&lt;/span&gt; tags, as in:&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;&lt;/p&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;pre class="c-sharp:collapse" name="code"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;...your source code snippet goes here...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;/pre&amp;gt; &lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;In case you're posting VB.NET code snippet then replace&lt;span style="font-family:trebuchet ms;"&gt;&lt;strong&gt; c-sharp&lt;/strong&gt;&lt;/span&gt; constructor parameter with &lt;strong&gt;&lt;span style="font-family:trebuchet ms;"&gt;vb&lt;/span&gt;&lt;/strong&gt;. If you want your code snippet expanded by default, omit &lt;span style="font-family:trebuchet ms;"&gt;&lt;strong&gt;:collapse&lt;/strong&gt;&lt;/span&gt; part of the constructor. But I suggest you always use collapsed source snippets due to physical message length and scrolling issues. Of course, don't forget to hit &lt;span style="font-family:trebuchet ms;"&gt;&lt;strong&gt;Save Now&lt;/strong&gt;&lt;/span&gt; button at the end.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-1680477411243443222?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/1680477411243443222/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2007/01/note-to-contributors.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/1680477411243443222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/1680477411243443222'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2007/01/note-to-contributors.html' title='A note to contributors'/><author><name>Maksim Sestic</name><uri>http://www.blogger.com/profile/11155932635442483931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3062125617693317780.post-5133789858623670592</id><published>2007-01-12T14:54:00.000+01:00</published><updated>2008-10-30T13:19:03.200+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Topology Framework .NET (TF.NET)'/><title type='text'>Topology Framework .NET (TF.NET)</title><content type='html'>Author: Sestic, Maksim&lt;br /&gt;&lt;br /&gt;Topology Framework .NET represents a topology manipulation API capable of handling managed objects representation of topological entities based on other popular APIs, exposing it's JTS-based common topology manipulation core to them.&lt;br /&gt;&lt;br /&gt;JTS Topology Suite is, in fact, Java API providing spatial object model and fundamental geometric functions, providing a complete, consistent, robust implementation of fundamental 2D spatial algorithms. It implements geometry model defined in the OpenGIS Consortium Simple Features Specification for SQL. JTS port for .NET was named NTS, and is fully conformant to Microsoft .NET 2.0 specification. NTS extends JTS with numerous coordinate transformation and other functions, while TF.NET extends NTS further, including additional IO functions and generic classes related to geometry graphs. For details regarding described technologies and their respective authors see acknowledgements below.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Provided Functions&lt;/strong&gt; &lt;p&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Spatial predicates (based on the &lt;a href="http://docs.codehaus.org/display/GEOTDOC/Point+Set+Theory+and+the+DE-9IM+Matrix"&gt;DE-9IM&lt;/a&gt; model)&lt;/li&gt;&lt;li&gt;Overlay functions (intersection, difference, union, symmetric difference)&lt;/li&gt;&lt;li&gt;Buffer Convex hull&lt;/li&gt;&lt;li&gt;Area and distance functions&lt;/li&gt;&lt;li&gt;Topological validity checking&lt;/li&gt;&lt;li&gt;Coordinate systems manipulation (transformations)&lt;/li&gt;&lt;li&gt;Topological graphs manipulation&lt;/li&gt;&lt;li&gt;Generic geometry I/O support: WKT, WKB, GML, SHP&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Supported External Managed APIs&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;OSGeo &lt;a href="http://fdo.osgeo.org/"&gt;Feature Data Objects&lt;/a&gt; (FDO) geometries&lt;/li&gt;&lt;li&gt;OSGeo &lt;a href="http://mapguide.osgeo.org/"&gt;MapGuide Server&lt;/a&gt; (FDO-based) geometries&lt;/li&gt;&lt;li&gt;Autodesk &lt;a href="http://usa.autodesk.com/adsk/servlet/index?id=773204&amp;amp;siteID=123112"&gt;ObjectARX&lt;/a&gt; geometries (a.k.a. entities)&lt;/li&gt;&lt;li&gt;Oracle &lt;a href="http://www.oracle.com/technology/tech/windows/odpnet/index.html"&gt;Data Provider for .NET&lt;/a&gt; (ODP.NET) geometries - see related &lt;a href="http://code.google.com/p/tf-net/wiki/OdpReaderWriter"&gt;wiki page&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Package Components Available For Download&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;TF.NET Core Library, a mandatory component exposing basic topology manipulation API. &lt;/li&gt;&lt;li&gt;TF.NET Reader/Writer for MapGuide, a reader/writer for geometric primitives exposed by OSGeo MapGuide Server. &lt;/li&gt;&lt;li&gt;TF.NET Reader/Writer for FDO, a reader/writer for geometric primitives exposed by OSGeo Feature Data Objects spatial library. &lt;/li&gt;&lt;li&gt;TF.NET Reader/Writer for ObjectARX, a reader/writer for geometric entities exposed by Autodesk AutoCAD and it's verticals.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;References And Further Reading&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;TF.NET &lt;a href="http://code.google.com/p/tf-net/downloads/list"&gt;API Help&lt;/a&gt; (CHM file) &lt;/li&gt;&lt;li&gt;JTS Topology Suite &lt;a href="http://www.vividsolutions.com/jts/javadoc/index.html"&gt;API Help&lt;/a&gt; &lt;/li&gt;&lt;li&gt;JTS Topology Suite &lt;a href="http://www.vividsolutions.com/jts/bin/JTS%20Technical%20Specs.pdf"&gt;Technical Specifications&lt;/a&gt; (PDF file) &lt;/li&gt;&lt;li&gt;JTS Topology Suite &lt;a href="http://www.vividsolutions.com/jts/bin/JTS%20Developer%20Guide.pdf"&gt;Developer's Guide&lt;/a&gt; (PDF file) &lt;/li&gt;&lt;li&gt;JTS Topology Suite explained on &lt;a href="http://www.jump-project.org/project.php?PID=JTS&amp;amp;SID=OVER"&gt;The Jump Project&lt;/a&gt; page &lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/tf-net/wiki/References"&gt;References and Further Reading&lt;/a&gt; wiki page&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Credits&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;TF.NET is primarily based on other people's work related to topology manipulation, hence special acknowledgement to them. Referred libraries were additionally repackaged and their namespaces renamed for easier use. Please download copyright disclaimer for detailed description.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Vivid Solutions' &lt;a href="http://www.vividsolutions.com/jts/jtshome.htm"&gt;JTS Topology Suite&lt;/a&gt; &lt;/li&gt;&lt;li&gt;Diego Guidi's &lt;a href="http://code.google.com/p/nettopologysuite/"&gt;NetTopologySuite&lt;/a&gt; &lt;/li&gt;&lt;li&gt;Morten Nielsen's &lt;a href="http://www.codeplex.com/SharpMap/"&gt;SharpMap&lt;/a&gt; &lt;/li&gt;&lt;li&gt;Urban Science Applications' &lt;a href="http://sourceforge.net/projects/geotoolsnet/"&gt;GeoTools.NET&lt;/a&gt; &lt;/li&gt;&lt;li&gt;Jonathan de Halleux's &lt;a href="http://www.codeplex.com/quickgraph/"&gt;QuickGraph&lt;/a&gt; &lt;/li&gt;&lt;li&gt;Ryan Seghers' &lt;a href="http://www.codeproject.com/cs/library/rtoolsutil.asp"&gt;RTools.Util&lt;/a&gt; &lt;/li&gt;&lt;li&gt;Jason Smith's &lt;a href="http://www.codeproject.com/csharp/sets.asp"&gt;Iesi.Collections&lt;/a&gt; &lt;/li&gt;&lt;li&gt;Kailuo Wang's &lt;a href="http://www.codeproject.com/csharp/GenericISet.asp"&gt;Iesi.Collections.Generic&lt;/a&gt; &lt;/li&gt;&lt;li&gt;Bruno Lowagie and Paulo Soares' &lt;a href="http://sourceforge.net/projects/itextdotnet/"&gt;iText&lt;/a&gt; &lt;/li&gt;&lt;li&gt;Dennis Jonio for articles on ODP.NET implementation &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;For more information please contact project owner: &lt;a href="mailto:max@geoinova.com" rel="nofollow"&gt;Maksim Sestic&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3062125617693317780-5133789858623670592?l=topologyframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://topologyframework.blogspot.com/feeds/5133789858623670592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://topologyframework.blogspot.com/2008/05/topology-framework-net-tfnet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/5133789858623670592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3062125617693317780/posts/default/5133789858623670592'/><link rel='alternate' type='text/html' href='http://topologyframework.blogspot.com/2008/05/topology-framework-net-tfnet.html' title='Topology Framework .NET (TF.NET)'/><author><name>Maksim Sestic</name><uri>http://www.blogger.com/profile/11155932635442483931</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
