I am trying to use manipulation on a UI element (rectangle) and can rotate and translate it without problem. What I would like to achieve is to make another UI element (ellipse for example) to follow the first (rectangle).
If I apply the same transform group -that I used for rectangle- to ellipse, during translation manipulation it works fine but during rotation ellipse does not follow rectangle.
I think I somehow must find a suitable composite transform center Point to provide to ellipse but I can not figure out how.
Here is corresponding sample code.
public MainPage()
{
this.InitializeComponent();
rectMy.ManipulationMode = ManipulationModes.None | ManipulationModes.TranslateX | ManipulationModes.TranslateY | ManipulationModes.Rotate;
rectMy.ManipulationStarted += rectMy_ManipulationStarted;
rectMy.ManipulationDelta += rectMy_ManipulationDelta;
rectMy.ManipulationCompleted += rectMy_ManipulationCompleted;
transformGroup.Children.Add(previousTransform);
transformGroup.Children.Add(compositeTransform);
rectMy.RenderTransform = transformGroup;
}
void rectMy_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
e.Handled = true;
}
void rectMy_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
previousTransform.Matrix = transformGroup.Value;
Point center = previousTransform.TransformPoint(new Point(rectMy.Width / 2, rectMy.Height / 2));
compositeTransform.CenterX = center.X;
compositeTransform.CenterY = center.Y;
compositeTransform.Rotation = e.Delta.Rotation;
compositeTransform.ScaleX = compositeTransform.ScaleY = e.Delta.Scale;
compositeTransform.TranslateX = e.Delta.Translation.X;
compositeTransform.TranslateY = e.Delta.Translation.Y;
}
void rectMy_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
{
e.Handled = true;
}
OK. I understood it better now and found the solution. It is all about the center point of the composite transform (as I initially guessed). For center of the ellipse, I had to feed the center of rectangle. However the coordinate needed to be given relative to the ellipse. In my case ellipse is at the right upper corner of the rectangle so below is what I have given as composite transform center.
Point centerE = previousTransformE.TransformPoint(new Point(-rectMy.Width / 2 + ellipseMy.Width / 2, rectMy.Height / 2 + ellipseMy.Height / 2));
For rectangle, the center point for composite transform was:
Point center = previousTransform.TransformPoint(new Point(rectMy.Width / 2, rectMy.Height / 2));
Stackoverflow does not allow me to post an image to better visualize the things. Sorry!
The whole code:
previousTransform.Matrix = transformGroup.Value;
previousTransformE.Matrix = transformGroupE.Value;
Point center = previousTransform.TransformPoint(new Point(rectMy.Width / 2, rectMy.Height / 2));
compositeTransform.CenterX = center.X;
compositeTransform.CenterY = center.Y;
compositeTransform.Rotation = e.Delta.Rotation;
compositeTransform.TranslateX = e.Delta.Translation.X;
compositeTransform.TranslateY = e.Delta.Translation.Y;
Point centerE = previousTransformE.TransformPoint(new Point(-rectMy.Width / 2 + ellipseMy.Width / 2, rectMy.Height / 2 + ellipseMy.Height / 2));
compositeTransformE.CenterX = centerE.X;
compositeTransformE.CenterY = centerE.Y;
compositeTransformE.Rotation = e.Delta.Rotation;
compositeTransformE.TranslateX = e.Delta.Translation.X;
compositeTransformE.TranslateY = e.Delta.Translation.Y;
Related
I'm trying to set dimension to the elements in a AssemblyInstance. The code operates with coordinates from the first element.
AssemblyInstance ass; //is found and is not null
ViewSection vsec = RevitAuxilaries.CreateAssemblyViewSection(uiapp, ass,
AssemblyDetailViewOrientation.ElevationFront, ElementId.InvalidElementId, 25);
//UIApplication,
AssemblyInstance, AssemblyDetailViewOrientation, TemplateId, scale // created
BoundingBoxXYZ bbox1 = ass.get_BoundingBox(uiapp.ActiveUIDocument.ActiveView);
XYZ ptmid = (bbox1.Max + bbox1.Min) * 0.5;
Element cropboxelm = RevitAuxilaries.GetViewCropBox(uiapp, vsec); //finds CropBox element,
//found
BoundingBoxXYZ bcropbox = vsec.CropBox;
XYZ center = new XYZ(ptmid.X, ptmid.Y, 0.5 * (bcropbox.Max.Z + bcropbox.Min.Z));
Line axis = Line.CreateBound(center, center + XYZ.BasisZ);
RevitAuxilaries.RotateElement2(uiapp, cropboxelm, axis, 0.6981); // UIApplication,, Element,
Line, angle// created
double dw = RevitAuxilaries.GetDimensionFromElement(uiapp, fi, Dimensions.enWidth); //found dw
// = 3.937
ptleft = new XYZ(31.501, -23.3878, 32.4803);
ptrght = new XYZ(31.501 + dw * Math.Cos(0.6981), -23.3878 + dw * Math.Sin(0.6981), 32.4803);
Line ln = RevitAuxilaries.CreateLineFromPoints(uiapp, ptleft, ptrght); //created
ReferenceArray refarr = new ReferenceArray();
refarr.Append(ln.GetEndPointReference(0));
refarr.Append(ln.GetEndPointReference(1));
Dimension dim = null;
using (Transaction trans = new Transaction(uiapp.ActiveUIDocument.Document, "CreADim"))
{
trans.Start();
dim = uiapp.ActiveUIDocument.Document.Create.NewDimension(viewsec, line, refarr);
if (!issame)
{
try
{ dim.ValueOverride = Convert.ToInt32(UnitUtils.Convert(dim.Value.Value,
UnitTypeId.Feet, UnitTypeId.Millimeters)).ToString(); }
catch { }
}
trans.Commit();
uiapp.ActiveUIDocument.RefreshActiveView();
}
ERROR: The direction of dimension is invalid
Error in function checkDir, line 939
What is here wrong?
Have you tried to create the exact same dimension in the exact same context manually through the end user interface? Does that complete as expected? If not, what error message does that generate? If yes, you can analyse the resulting model, its elements and their properties using RevitLookup and possibly discover some required settings that can be added to your API approach.
I have a camera as child within a Group object and I need to get the origin/direction:
var cameraRig = new THREE.Group();
cameraRig.add( cameraPerspective );
cameraRig.add( cameraOrtho );
scene.add( cameraRig );
function relativeMousePosition () {
var canvasBoundingBox = renderer.domElement.getBoundingClientRect();
var mouse3D = new THREE.Vector3(0, 0, 0.5);
mouse3D.x = ((mouseX - 0) / canvasBoundingBox.width) * 2 - 1;
mouse3D.y = -((mouseY - 0) / canvasBoundingBox.height) * 2 + 1;
return mouse3D;
}
cameraRig.position.set(89,34,91);
cameraRig.lookAt(something.position);
cameraPerspective.position.set(123,345,123);
var dir = relativeMousePosition().unproject(camera).sub(cameraPerspective.position).normalize();
var origin = cameraPerspective.position;
The above code gives a origin + direction with the context of the cameraRig. When I exclude the camera out, having the scene as direct parent, it gives me the world origin/direction which I want. So how to incorporate the cameraRig to get world origin/direction, so I can do picking or whatever?
FIDDLE: https://jsfiddle.net/647qzhab/1/
UPDATE:
As mentioned in the comment by Falk:
var dir = relativeMousePosition().unproject(camera).sub(cameraPerspective.getWorldPosition()).normalize();
var origin = cameraPerspective.getWorldPosition();
The result is better, but not yet fully satisfiing, as the camera rotation seems not applied yet.
I need to update matrixWorld for the cameraRig:
cameraRig.position.set(89,34,91);
cameraRig.lookAt(something.position);
cameraPerspective.position.set(123,345,123);
cameraRig.updateMatrixWorld(true);
cameraPerspective.updateMatrixWorld(true);
Here is the situation. In my app I have an overlay layer that is composed of a transparent PNG. I have replaced the hitarea for the png with a 1x1 image using the following code:
[Bindable]
[Embed(source = "/assets/1x1image.png")]
private var onexonebitmapClass:Class;
private function loadCompleteHandler(event:Event):void
{
// Create the bitmap
var onexonebitmap:BitmapData = new onexonebitmapClass().bitmapData;
var bitmap:Bitmap;
bitmap = event.target.content as Bitmap;
bitmap.smoothing = true;
var _hitarea:Sprite = createHitArea(onexonebitmap, 1);
var rect:flash.geom.Rectangle = _box.toFlexRectangle(sprite.width, sprite.height);
var drawnBox:Sprite = new FlexSprite();
bitmap.width = rect.width;
bitmap.height = rect.height;
bitmap.x = -loader.width / 2;
bitmap.y = -loader.height / 2;
bitmap.alpha = _alpha;
_hitarea.alpha = 0;
drawnBox.x = rect.x + rect.width / 2;
drawnBox.y = rect.y + rect.height / 2;
// Add the bitmap as a child to the drawnBox
drawnBox.addChild(bitmap);
// Rotate the object.
drawnBox.rotation = _rotation;
// Add the drawnBox to the sprite
sprite.addChild(drawnBox);
// Set the hitarea to drawnBox
drawnBox.hitArea = _hitarea;
}
private function createHitArea(bitmapData:BitmapData, grainSize:uint = 1):Sprite
{
var _hitarea:Sprite = new Sprite();
_hitarea.graphics.beginFill(0x900000, 1.0);
for (var x:uint = 0; x < bitmapData.width; x += grainSize)
{
for (var y:uint = grainSize; y < bitmapData.height; y += grainSize)
{
if (x <= bitmapData.width && y <= bitmapData.height && bitmapData.getPixel(x, y) != 0)
{
_hitarea.graphics.drawRect(x, y, grainSize, grainSize);
}
}
}
_hitarea.graphics.endFill();
return _hitarea;
}
This is based off the work done here: Creating a hitarea for PNG Image with transparent (alpha) regions in Flex
Using the above code I am able to basically ignore the overlay layer for all mouse events (click, double click, move, etc.) However, I am unable to capture the right click (context menu) event for items that are beneath the overlay.
For instance I have a spell check component that checks the spelling on any textitem and like most other spell checkers if the word is incorrect or not in the dictionary underlines the word in red and if you right click on it would give you a list of suggestions in the contextmenu. This is working great when the text box is not under the overlay, but if the text box is under the overlay I get nothing back.
If anyone can give me some pointers on how to capture the right click event on a textItem that is under a transparent png that would be great.
How does one go about giving a title to the axis in prefuse scatter plot?
At the moment my code reads the data from the file and a range for both x and y axis works in the code. All I need to do now is to add titles/names for the axis. The code I have at the moment shows:
//set up the actions
AxisLayout xaxis = new AxisLayout(group, "GD",
Constants.X_AXIS, VisiblePredicate.TRUE);
AxisLayout yaxis = new AxisLayout(group, POINTS,
Constants.Y_AXIS, VisiblePredicate.TRUE);
//yaxis.setScale(Constants.LOG_SCALE);
yaxis.setRangeModel(receiptsQ.getModel());
receiptsQ.getNumberModel().setValueRange(0,120,0,120);
xaxis.setLayoutBounds(m_dataB);
yaxis.setLayoutBounds(m_dataB);
// sets group,axis,values,bounds
AxisLabelLayout ylabels = new AxisLabelLayout("ylab", yaxis, m_ylabB);
NumberFormat nf= NumberFormat.getInstance();
nf.setMaximumFractionDigits(0);
ylabels.setNumberFormat(nf);
// AxisLabelLayout xlabels = new AxisLabelLayout("goal diff", xaxis, m_xlabB, 15);
AxisLabelLayout xlabels = new AxisLabelLayout("xlab",xaxis,m_xlabB,5);
// vis.putAction("xlabels", xlabels);
vis.putAction("xlabels", xlabels);
You have to do it by hand. I've done this and my code is open source, so you're welcome to take a look at it:
https://github.com/brycecr/msmexplorer/blob/acacia/MSMExplorer/src/edu/stanford/folding/msmexplorer/util/axis/AxisRotateRenderer.java
https://github.com/brycecr/msmexplorer/blob/acacia/MSMExplorer/src/edu/stanford/folding/msmexplorer/util/axis/AxisLabelLabelLayout.java
In the label renderer, all the labels are drawn as a combination of a line and a label. In this class, we just add an additional item to the layout with our graph.
This is not super clean at all...in particular, a line (actually one pixel) is still rendered for the label, but I'm lazy and this suits my needs...I think you could improve this if necessary, but you'd probably need to reach into the axis renderer and make it draw no line for your label items.
Let me know if you have any questions about the operation of this.
#Override
public void run(double frac) {
super.run(frac);
setLabPos(item, length/2.0d + width, bounds);
}
/**
* Set the layout values for an axis label item.
*/
protected void setLabPos(VisualItem item, double xOrY, Rectangle2D b) {
switch (getAxis()) {
case Constants.X_AXIS:
xOrY = super.isAscending() ? xOrY + b.getMinX() : b.getMaxX() - xOrY;
PrefuseLib.updateDouble(item, VisualItem.X, xOrY);
PrefuseLib.updateDouble(item, VisualItem.Y, b.getMaxY() + label.getFont().getSize()/3.0d + gridLab.getFont().getSize());
PrefuseLib.updateDouble(item, VisualItem.X2, xOrY);
PrefuseLib.updateDouble(item, VisualItem.Y2, b.getMaxY() + label.getFont().getSize()/3.0d + gridLab.getFont().getSize());
break;
case Constants.Y_AXIS:
xOrY = super.isAscending() ? b.getMaxY() - xOrY - 1 : xOrY + b.getMinY();
PrefuseLib.updateDouble(item, VisualItem.X, b.getMinX());
PrefuseLib.updateDouble(item, VisualItem.Y, xOrY);
PrefuseLib.updateDouble(item, VisualItem.X2, b.getMinX());
PrefuseLib.updateDouble(item, VisualItem.Y2, xOrY);
}
}
}
How do I add a drop shadow (with defined distance, size etc) using Photoshop scripting?
Current JS Code
var fontSize = 14;
var fontName = "Arial-Bold"; // NB: must be postscript name of font!
// This is the colour of the text in RGB
//Click foreground colour in Photoshop, choose your colour and read off the RGB values
//these can then be entered below.
var textColor = new SolidColor();
textColor.rgb.red = 255;
textColor.rgb.green =255;
textColor.rgb.blue = 255;
var newTextLayer = doc.artLayers.add();
newTextLayer.kind = LayerKind.TEXT;
newTextLayer.textItem.size = fontSize;
newTextLayer.textItem.font = fontName;
newTextLayer.textItem.contents = ++Count;
newTextLayer.textItem.color = textColor;
newTextLayer.textItem.kind = TextType.PARAGRAPHTEXT;
newTextLayer.textItem.height = fontSize;
newTextLayer.textItem.width = doc.width -20;
//The line below is the text position (X Y) IE; 10 Pixels Right 10 Pixels Down
newTextLayer.textItem.position = Array(10, 12);
// Can be RIGHTJUSTFIED LEFTJUSTIFIED CENTERJUSTIFIED
newTextLayer.textItem.justification=Justification.CENTERJUSTIFIED;
I believe there is no API function for this.
The best you can do is to use Scriptlistner.
The code that it generates then can be used in your script.
Here are some similar discussion with Scriptlistner-generated code:
http://ps-scripts.com/bb/viewtopic.php?t=586
or
http://ps-scripts.com/bb/viewtopic.php?t=2207