CADability dotNET
Here you find code examples for using CADability.
C#: Position an IGeoObject on the surface of a Solid or Face
This sample code implements an Action derived from ConstructAction. The Action requires three inputs: A filename for a Picture, a location (preferrable but not necesarrily on a surface) and an optional scaling factor for the Picture. When the filename is specified and the mouse cursor is moved, the bitmap will be moved accordingly. If the mouse cursor hovers above a Surface, the bitmap is positioned parallel to that surface in that point with a small offset above the surface.
Source Code
CopyC#
using System; using System.Collections.Generic; using System.Text; using CADability.UserInterface; using CADability.GeoObject; using CADability.Shapes; using CADability.Curve2D; using CADability.Attribute; using Wintellect.PowerCollections; using CADability.Actions; using CADability; namespace TestCADability { /// <summary> /// Sample code for a CADability Action which places a bitmap picture object onto a surface /// of some solid object. To use this Action call Frame.SetAction /// </summary> class PositionObjectAction : ConstructAction { StringInput fileNameInput; // input field for the filename of the bitmap GeoPointInput positionInput; // input field for the position of the bitmap DoubleInput scalingFactorInput; // optional input field for a scaling factor for the bitmap Picture picture; // the picture object beeing placed string fileName; // the filename for the bitmap double scalingFactor; // the scaling factor GeoPoint location; // the location of the picture object /// <summary> /// Must be overriden, returns some ID for the action /// </summary> /// <returns>The ID</returns> public override string GetID() { return "PositionObjectAction"; } /// <summary> /// Overrides ConstructAction.OnSetAction. Provides the input fields and some initialsation /// </summary> public override void OnSetAction() { // Create and initialize the filename input field fileNameInput = new StringInput("PositionBitmap.Filename"); // Resource ID must be defined in StringTable fileNameInput.IsFileNameInput = true; // to enable the openfile dialog // you may also wnat to set fileNameInput.FileNameFilter fileNameInput.GetStringEvent += new StringInput.GetStringDelegate(OnGetFileName); fileNameInput.SetStringEvent += new StringInput.SetStringDelegate(OnSetFileName); fileName = ""; // initial filename is empty // Create and initialize the position input field positionInput = new GeoPointInput("PositionBitmap.Position"); // Resource ID must be defined in StringTable positionInput.GetGeoPointEvent += new GeoPointInput.GetGeoPointDelegate(OnGetPosition); positionInput.SetGeoPointExEvent += new GeoPointInput.SetGeoPointExDelegate(OnSetPosition); // Create and initialize the scaling factor input field scalingFactorInput = new DoubleInput("PositionBitmap.Scale"); // Resource ID must be defined in StringTable scalingFactorInput.GetDoubleEvent += new DoubleInput.GetDoubleDelegate(OnGetScalingFactor); scalingFactorInput.SetDoubleEvent += new DoubleInput.SetDoubleDelegate(OnSetScalingFactor); scalingFactorInput.Optional = true; // optinal input scalingFactorInput.ForwardMouseInputTo = positionInput; // no mouse input, forward to position input scalingFactor = 1.0; // default scaling factor // picture must exist prior to SetInput // because picture.Location is required by positionInput picture = Picture.Construct(); // Define the input fields for the ConstructAction base.SetInput(fileNameInput, positionInput, scalingFactorInput); base.OnSetAction(); // Default implementation must be called // force the snapmode to include SnapToFaceSurface base.Frame.SnapMode |= SnapPointFinder.SnapModes.SnapToFaceSurface; } /// <summary> /// Will be called when some number is entered into the scaling factor input field /// </summary> /// <param name="val">The new value</param> /// <returns>true, if accepted</returns> bool OnSetScalingFactor(double val) { if (val > 0.0) // accept only positive values { scalingFactor = val; // save value return true; } return false; } /// <summary> /// Called by the scaling factor input field to determine which number to display /// </summary> /// <returns></returns> double OnGetScalingFactor() { return scalingFactor; } /// <summary> /// Called when the position input is changed /// </summary> /// <param name="p">The new location point</param> /// <param name="didSnap">Information on point snapping</param> /// <returns>true, if point is accepted</returns> bool OnSetPosition(GeoPoint p, SnapPointFinder.DidSnapModes didSnap) { location = p; // default vectors for the two sides of the bitmap GeoVector dirWidth = GeoVector.XAxis; GeoVector dirHeight = GeoVector.ZAxis; if (didSnap == SnapPointFinder.DidSnapModes.DidSnapToFaceSurface) { // if there was a snap on the surface of a face we want to center the picture object // there. We also want to make it parallel to the surface at this point and stand upright. Face fc = base.LastSnapObject as Face; // this object was involved in the snapping if (fc != null) // should always be the case { GeoPoint2D pos = fc.Surface.PositionOf(location); // position in the surface u/v system GeoVector normal = fc.Surface.GetNormal(pos); // normal vector at this position Projection projection = base.CurrentMouseView.Projection; // the projection of the view if (projection != null) { // make sure that the normal vector points away from the user. // On faces not in a solid both sides of the face are displayed and you don't know // on which side you are if (projection.Direction * normal < 0.0) normal = -normal; } location = location - 0.001 * normal.Normalized; // moves the location point a little bit // in the direction of the normal vector to the user so // that the bitmap hoovers a little above the surface to avoid display artefacts if (Precision.SameDirection(normal, GeoVector.ZAxis, false)) { // the surface is parallel to the x/y plane: orient the bitmap to the x/y axis dirWidth = GeoVector.XAxis; dirHeight = GeoVector.YAxis; } else { // some arbitrary surface direction: calculate the base direction of the bitmap to // be parallel to the x/y plane and the up direction rectangular to the base and the normal. // this makes the bitmap appear upright (in the sense of the z-axis) dirWidth = normal ^ GeoVector.ZAxis; dirHeight = dirWidth ^ normal; dirWidth.Norm(); // we need normalized vectors dirHeight.Norm(); } } } double w = 1; // default width and height if there is no bitmap yet double h = 1; if (picture.Bitmap != null) { // width and height of the bitmap w = picture.Bitmap.PhysicalDimension.Width; h = picture.Bitmap.PhysicalDimension.Height; } // provide the picture object with proper aspect ratio and scaling according to the scaling factor picture.DirectionWidth = w * scalingFactor * dirWidth; picture.DirectionHeight = h * scalingFactor * dirHeight; // set the location of the object so that the center of the bitmap occures at the position of location // Since picture.Location is the lower left point of the object we must move it left and down // with half of it's size picture.Location = location - 0.5 * picture.DirectionWidth - 0.5 * picture.DirectionHeight; return true; // this was OK } /// <summary> /// Called by the position input field to get the current location /// </summary> /// <returns></returns> GeoPoint OnGetPosition() { return location; } /// <summary> /// Called by the filename input field when the filename changes /// </summary> /// <param name="val">The new file name</param> void OnSetFileName(string val) { fileName = val; // save the name System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(fileName); // load the bitmap picture.Bitmap = bmp; // set the bitmap to the picture object base.ActiveObject = picture; // set the active object: // now that we have a bitmap we set this object as the active object, which means // that is will be displayed while the location is positioned and at the end of the // action it will automatically be inserted into the model } /// <summary> /// Called by the filename input field when the filename string is required /// </summary> /// <returns>the filename</returns> string OnGetFileName() { return fileName; } } }