I have created a vtkLineSource that is passed to vtkPolyDataMapper, passed to vtkActor.
actor->GetProperty()->SetLineStipplePattern(0xf0f0);
works like a charm. However
actor->GetProperty()->SetLineWidth(5.0);
does nothing.
Both methods are marked "This is only implemented for OpenGL."
Here's the snippet:
vtkSmartPointer<vtkLineSource> line1 = vtkSmartPointer<vtkLineSource>::New();
line1->SetPoint1(posvel1.x, posvel1.y, posvel1.z);
line1->SetPoint2(posvel2.x, posvel2.y, posvel2.z);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(line1->GetOutputPort());
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetLineWidth(2.0); // TODO: Has no effect.
actor->GetProperty()->SetColor(1, 1, 1);
actor->GetProperty()->SetOpacity(0.5);
actor->GetProperty()->SetLineStipplePattern(0xf0f0);
actor->GetProperty()->SetLineStippleRepeatFactor(1);
// Further up, add actor to vtkAssembly
Line shows and has stipple pattern, but width is unaffected by whatever value I pass to SetLineWidth.
Edit: I already had a comment in my code. "Replace with vtkPoints polygon drawing instead of LineSource needed probably..." Tested this: Does not solve the issue, stipple pattern is there, line width does not work.
== Edit ==
What alternatives are there to draw a 2D dashed/dotted line in a 3D scene with vtk?
Related
I do not know how to set the position of a instance in gd script. The instanced shows up on the corner of the screen.
Thanks :)
It depends on what type of instance. If it's an object that has been derived from something like a Node2D, then position.x or position.y should do it. Do you have any code we can look at?
Depends on whether you want 2D or 3D.
A common method is as such:
Create the object you want to instance in its own scene.
Save the object as a scene (.tscn file) - for example "Scene1.tscn"
Call upon your instanced scene from your main scene as follows:
Make sure to preload the scene you plan to instance before your ready() function. For example if was called "Scene1", then declare :
onready var Scene1 = preload("res://Scene1.tscn")
Then, later in your code when you want to call an instance of the scene, do it as such:
var InstancedScene = Scene1.instance()
add_child(InstancedScene)
// This simply instances the scene (I think at co-ordinates (0,0,0)), but you can tell it where to instance it using the following example:
For 3D use:
InstancedScene.transform.origin = Vector3(50.0, 0.0, -50.0)
//Gives position x=50, y=0, x=-50.
This can also be used for rotation, just specify transform.basis and give a similar Vector3 coordinate set.
OR for 2D use:
InstancedScene.position = Vector2(100.0, 100.0)
//This instances the object 100 pixels across and 100 pixels down. Sub in whatever values you need. You can also specify a rotation using InstancedScene.rotation_degrees = 45 (To give 45 degrees for example)
I can't seem to get a QGraphicsEllipseItem to show up in my view. I am attempting to use it in combination with a QGraphicsLineItem:
# Instantiate the line object:
self.profileLine = QGraphicsLineItem()
self.profileLine.setPen(QPen(Qt.yellow, 1.0))
self.profileLine.setLine(self.StartX, self.StartY, self.StopX, self.StopY)
self.scene.addItem(self.profileLine)
# Instantiate the circle:
self.profileStopHandle = QGraphicsEllipseItem()
self.profileStopHandle.setPen(QPen(Qt.yellow, 1.0))
self.profileStopHandle.setRect(self.StopX, self.StopY, 50, 50)
self.scene.addItem(self.profileStopHandle)
Later, in my mouse move event, I determine the current mouse coordinates, assign them to StopX/StopY and redraw the line from the start point to the new stop point as well as draw the ellipse around the new stop point:
self.profileLine.setLine(self.StartX, self.StartY, self.StopX, self.StopY)
self.profileStopHandle.setPos(self.StopX, self.StopY)
The line shows up fine and behaves just as it should, but no matter what I cannot seem to get the ellipse to draw. I know the point coordinates I'm passing to it are correct because they are the same ones I'm using for the line. The ellipse just never appears as if it was never created in the first place. What am I doing wrong here (it must be something very basic)? Thank you in advance.
The issue was the Z-value (amateur mistake). I brought the ellipse to the foreground and now it is visible:
self.profileStopHandle.setZValue(self.sceneImage.zValue() + 1.0)
How would I go about changing the registration point of a movieclip labeled "tablet" placed on the stage (root) dynamically?
For example: I have the following:
var tablet = this.tablet; //movieclip labeled "tablet" on stage
function resetTablet(){
tablet.regX = tablet.width/2; //move registration point to center
tablet.regY = tablet.height/2;
}
However when I call it using GSAP:
var tl = new TimelineLite();
tl.to(tablet, 1, {alpha:1, onComplete:resetTablet})
.to(tablet, 3, {alpha:0, scaleX:1.5, scaleY:1.5})
the registration point is still set to the upper left corner rather than the center.
What am I doing wrong here? Thanks!
Registration points affect change both the transformation point, but also the position. If you set a displayobject that is 100x100 pixels to regX=50;regY=50, then it will draw from that point, moving the content 50px to the top and left. If you make that change you should also translate the clip to x=50;y=50.
An issue with you example is that there is no width or height on EaselJS content (explained here). You can get the bounds of anything generated by Flash CC using the nominalBounds property, which Flash exports as a property on every object. If you have multiple frames, you can turn on "multi-frame bounds" in the publish settings, and a frameBounds property is added to the objects as well.
Note that nominalBounds and frameBounds are not used by the getBounds method.
Here is how you might be able to approach it.
var bounds = tablet.nominalBounds;
tablet.regX = bounds.width/2;
tablet.regY = bounds.height/2;
// Optional if your actual registration point was [0,0] before:
tablet.x += tablet.regX;
tablet.y += tablet.regX;
Hope that helps.
Here's the fiddle: http://jsfiddle.net/DevChefOwen/CZ6Dp/
var text = g.append("text")
.style("font-size",30)
.style("fill","#000")
.attr("dy",0)
.append("textPath")
.attr("xlink:href","#yyy")
.style("text-anchor","left") // using "end", the entire text disappears
.text("some text");
I've tried a number of different things to no avail. The left align is the easy part. If you did a middle, though, you see only "text" instead of "some text", implying that "some" is just hidden because it went "out of span" for the given arc.
If, however, I added:
.attr("startOffset","39%")
(as in here: http://jsfiddle.net/DevChefOwen/2H99c/)
It would look right aligned, but outside of programmatically trying to get the width/height of the text element and look for sharp changes in width/height (which seems wrong and likely error-prone), I can't seem to find a way to right align the text.
I've also tried using an SVG path (essentially a curved arc line) and the same disappearing act happens with the text when "text-anchor" is set to "left".
Thanks ahead for your time!
The question is somewhat confusing matters. The issue isn't aligning text at the end of the path -- that's easy to do with "text-anchor"="end" and "startOffset"="100%".
However, using those settings with the path created by the d3 arc function, you end up with the text cornering around the end of the inside curve and the left straight edge, to the end of the path as defined by the arc function:
http://jsfiddle.net/CZ6Dp/8/
The real issue is that the path that you want the text to be aligned along (the outside arc of the shape) is only one segment of the path that defines the shape.
(By the way, "left" and "right" are not valid values for the "text-anchor" property, and will just be ignored).
The answer by #defghi1977 gives one way to approach the problem, by figuring out the length of the path segment that you do want to use and adjusting the start offset accordingly.
Another way to approach the problem is to create a separate path (not drawn on screen) that represents only the part of the path that you want to be used for positioning text.
There are a number of possible ways to create a path that only represents the outside arc (some example code here). #defghi1977's approach of grabbing it from the existing path with regular expressions is probably the most efficent for your situation. But instead of just creating a temporary element to calculate a length, I actually have to add the new path to the DOM so it can be used as the reference path for the <textPath> element. (Which I suppose is the downside to this approach -- twice as many DOM elements!)
var path = g.append("svg:path")
.attr("d", arct)
.style("fill","#ccc")
.attr("transform", "translate("+cfg.w/2+","+cfg.h/2+")")
.each(function(d,i) {
var justArc = /(^.+?)L/;
//grab everything up to the first Line statement
var thisSelected = d3.select(this);
var arcD = justArc.exec( thisSelected.attr("d") )[1];
defs.append("path")
.attr("id", "yyy") //normally the id would be based on the data or index
.attr("d", arcD)
.attr("transform", thisSelected.attr("transform") );
//if you can avoid using transforms directly on the path element,
//you'll save yourself having to repeat them for the text paths...
});
var text = g.append("text")
.style("font-size",30)
.style("fill","#000")
.attr("dy",0)
.append("textPath")
.attr("xlink:href","#yyy")
.style("text-anchor","end")
.attr("startOffset","100%")
.text("some text");
http://jsfiddle.net/CZ6Dp/9/
Again, factoring in the extra DOM load #defghi1977's method is probably slightly preferrable, although this version has the benefit of not being dependent on browser support for getTotalLength. But as far as I know that method is fairly well implemented.
So just consider this an alternate approach for completeness' sake.
This path is constructed by 4(or 5) path segments.
So, this probrem will be solved to get first arc path length.
But I don't know how to get sub path length by using d3.js, thus I use svgdom directly.
I tried to fix your code. If this code is not what you hope, I'm sorry.
path-anchor attribute to end.
define function to get startOffset value.
var path = g.append("svg:path")
.attr("id","yyy")
.attr("d", arct)
.style("fill","#ccc")
.attr("transform", "translate("+cfg.w/2+","+cfg.h/2+")");
var text = g.append("text")
.style("font-size",30)
.style("fill","#000")
.attr("dy",0)
.append("textPath")
.attr("xlink:href","#yyy")
//.style("text-anchor","left") // using "end", the entire text disappears
.attr("text-anchor", "end")
.text("some text")
.attr("startOffset",function(){
var d = document.getElementById("yyy").getAttribute("d");
var tmp = document.createElementNS("http://www.w3.org/2000/svg" ,"path");
//get the arc segment of path
var arc = d.match(/(^.+?)L/)[1];
tmp.setAttribute("d", arc);
//return offset position
return tmp.getTotalLength();
});
I think the confusion comes from the meaning of text-anchor - it's not "relative to where on the parent will I justify" but rather "what part of me should I align to the start".
You're right to try to use startOffset to move the origin. Since the outer radius of your path is longer than the inner radius, the correct start offset is a little more than half of the path (around 53%).
Just a little more twiddling with your settings and you should have it. Here's a fiddle with my interpretation of what you're looking for.
the problem I am having it that if inside the UIView Draw override, I change the view frame size, drawing a rectangle is not working as expected.
If I change the view frame size outside of the Draw override, it works fine. Is this an expected behavior or is it a problem with monotouch only?
This is the code I am using:
class ChildView : UIView
{
public override void Draw (RectangleF rect)
{
base.Draw (rect);
CGContext g = UIGraphics.GetCurrentContext();
//adding 30 points to view height
RectangleF rec = new RectangleF(this.Frame.Location,this.Frame.Size);
rec.Height+=30;
RectangleF rec_bounds = new RectangleF(0,0,rec.Width,rec.Height);
this.Frame=rec;
this.Bounds=rec_bounds;
//drawing a red rectangle to the first half of view height
UIColor.Red.SetFill();
RectangleF _rect = new RectangleF(this.Bounds.Location,this.Bounds.Size);
_rect.Height=_rect.Height/2;
g.FillRect(_rect);
}
}
However, the output of this code is this: (it should draw only 30 points red, but it draws 60 points)
Here is a link to download the project to reproduce this issue:
www.grbytes.com\downloads\RectangleDrawProblem.rar
Καλημέρα!
This behavior is expected. If you want to change the view's frame inside the Draw override, do it before getting the current context. That is because the graphics context also has a size and that is the size of the view at the time you are retrieving it.
Also, there is no need to set both the Bounds and the Frame of the view. You can just set either of them in this case.
By the way, I don't think you need to call base.Draw(). According to the Apple documentation, "If you subclass UIView directly, your implementation of this method does not need to call super."