getattribute in OSL is not giving expected results - maya

I'm working on a custom OSL shader for Maya. I'm adding attributes to the shape node of objects and using getattribute() in my OSL code to manipulate those attributes. I have attributes for color correct, base color, rim width and rim color. (the last 2 are for facing ratio). My OSL always compiles and I'm always able to connect it to the material I'm using. But every time I check if it's working in the Arnold render view, my sliders on my attributes don't do anything. The goal is to have an image file connected to the base color of the material and have the color correct node affect base color (which would affect the texture file)
At first I thought my problem was I was trying to do too much in a single OSL node (I was using getattribute for all of the attributes I listed above). So I tried isolating it to just the color correct attribute and still nothing. Is anyone familiar with OSL and can help me?
This is what my OSL code is for color correct:
shader
colorCorrect
(
float modifier = 1[[float min = 0, float max = 72]],
color bob = 0,
output color result = 0
)
{
color temp = transformc("rgb", "hsv", bob);
temp[0] = temp[0] * modifier;
result = transformc("hsv", "rgb", temp);
}
This is what my OSL code is for facing ratio:
shader
Velvet(
float rim_width = 0.2
[[
string label = "Rim Width",
]],
color basecolor = color(1,1,1)
[[
string label = "Base Color",
string widget = "checkBox",
]],
color rimcolor = color(1,0,0)
[[
string label = "Rim Color",
]],
output color resultRGB = 0,
output float resultF = 0)
{
vector i = normalize(I);
vector n = normalize(N);
float d = fabs(dot(-i, n));
d = smoothstep(rim_width, 1.0, d);
getattribute("base_color", resultRGB = mix(rimcolor, basecolor, d));
getattribute("rim_width", resultF = d - 0.5);
}

Related

Getting black and white image when doing rotation?

I want to rotate my image by 45 degree. I have defined a function for the same. When I run it over my RGB images, it is getting saved as grayscale images?
def rotateImage(image, angle):
row,col = image.shape
center=tuple(np.array([row,col])/2)
rot_mat = cv2.getRotationMatrix2D(center,angle,1.0)
new_image = cv2.warpAffine(image, rot_mat, (col,row))
return new_image
rotate_img_path = '../data/rotate_45_img'
rotate_mask_path = '../data/rotate_45_mask'
real_img_path = '../data/img'
real_mask_path = '../data/mask'
for img in os.listdir(real_img_path):
edge_img = cv2.imread(os.path.join(real_img_path,img))
edges = rotateImage(edge_img, 45)
cv2.imwrite(os.path.join(rotate_img_path, img), edges)
print("Finished Copying images")
for img in os.listdir(real_mask_path):
edge_img = cv2.imread(os.path.join(real_mask_path,img))
edges = rotateImage(edge_img, 45)
cv2.imwrite(os.path.join(rotate_mask_path, img), edges)
# cv2.imwrite('edge_' + '.jpg', edges)
print("Finished Copying masks")
A clue here may be
row,col = image.shape
which would raise an error if image was three dimensional (i.e., in color with separate channels for B, G, and R) instead of two (i.e., grayscale). Unless you're reading RGB images with code not shown here, this suggests that your images are already grayscale.

Swift - Create circle and add to array

I've been looking for a little while on how to create a circle in Swift, but it seems quite complicated. I want to create a circle at run time, with a specified x and y, and width and height. I then want to add this circle to an array where I can create more circles and add to it.
How do I do this?
Edit: This is what I've tried so far:
var center : CGPoint = touchLocation
var myContext : CGContextRef = UIGraphicsGetCurrentContext()
let color : [CGFloat] = [0, 0, 1, 0.5]
CGContextSetStrokeColor (myContext, color);
CGContextStrokeEllipseInRect (myContext, CGRectMake(touchLocation.x, touchLocation.y, 20, 20));
touchLocation is the location of the users finger. This crashes on execution on this line:
var myContext : CGContextRef = UIGraphicsGetCurrentContext()
The error says "Unexpectedly found nil while unwrapping an Optional value
Also, this doesn't allow me to add the circle to an array, because I don't know what variable type it is.
There are many ways to draw a circle, here is a snippet that I have been hacking with:
func circleWithCenter(c:CGPoint, radius r:CGFloat,
strokeColor sc: UIColor = UIColor.blackColor(),
fillColor fc: UIColor = UIColor.clearColor()) -> CAShapeLayer {
var circle = CAShapeLayer()
circle.frame = CGRect(center:c, size:CGSize(width:2*r, height:2*r))
circle.path = UIBezierPath(ovalInRect:circle.bounds).CGPath
circle.fillColor = fc.CGColor
circle.strokeColor = sc.CGColor
circle.fillColor = fc == UIColor.clearColor() ? nil : fc.CGColor
return circle
}
Note that I extended CGRect (using Swift specific features) to add a initializer that takes a center, but that is not material to your question.
Your code is not "creating" a circle as an object, it is attempting to draw one in the graphics context. What you need to do is to create a bezier path object, draw into that and save the path in your array. Something like:
var circleArray = [CGMutablePathRef]()
// ...
let path: CGMutablePathRef = CGPathCreateMutable()
CGPathAddArc(path, nil, touchLocation.x, touchLocation.y, radius, 0, M_PI * 2, true)
circleArray += [path]
You then need to stroke the path(s) in your draw routine.

Saving GeoTiff with color scheme

I am trying to save a numpy array output as a GeoTiff, and have the code running mostly successfully, but the output image has a sepia-toned scale for the data (instead of a normal color scheme like my code produces for the image), and a black background (instead of the white/no-data background that my code produces for the image).
Here's the code for saving my array to a GeoTiff. Can I add a line in somewhere about making no-data = 0, and making the data scheme be colored?
from osgeo import gdal, osr, ogr, os
from gdalconst import *
def array2raster(newRasterfn,rasterOrigin,pixelWidth,pixelHeight,array):
cols = array.shape[1]
rows = array.shape[0]
originX = rasterOrigin[0]
originY = rasterOrigin[1]
driver = gdal.GetDriverByName( 'GTiff' )
outRaster = driver.Create(newRasterfn, cols, rows, 1, gdal.GDT_Float32)
outRaster.SetGeoTransform((originX, pixelWidth, 0, originY, 0, pixelHeight))
outband = outRaster.GetRasterBand(1)
outband.WriteArray(array)
# outRaster = driver.Create( 'CORDC_GTIFF/working_CA.tiff', 300, 300, 1, gdal.GDT_Int32)
proj = osr.SpatialReference()
proj.ImportFromEPSG(4326)
outRaster.SetProjection(proj.ExportToWkt())
# geotransform = (1,0.1,0,40,0,0.1)
rasterOrigin = (-127,42)
pixelWidth = .01
pixelHeight = .01
newRasterfn = 'CORDC_GTIFF/cordc_working_CA.tif'
array = np.array(spd)
reversed_arr = array[::-1] # reverse array so the tif looks like the array
array2raster(newRasterfn,rasterOrigin,pixelWidth,pixelHeight,reversed_arr) # convert array to raster
You can set the no data value using the band's SetNoDataValue method:
outband = outRaster.GetRasterBand(1)
outband.SetNoDataValue(0)
outband.WriteArray(array)
Areas matching the no data value should then be displayed as transparent

SolidColourBrush in Silverlight

r= byte.Parse(colours[0]); = 255
g= byte.Parse(colours[1]); = 0
b = byte.Parse(colours[2]); = 0
I have the RGB values as shown above.When i try to use the variables and retrieve the color I am not getting any color in my HMI but when i pass the same values directly i am able to get the color in my silverlight HMI
zoneColour.Color = Color.FromArgb(255,r,g,b); - DOES NOT WORK
zoneColour.Color = Color.FromArgb(255,255,0,0); -WORKS
May this helps you:
//r,g and b must be in integer data type
zoneColor.Color = new SolidColorBrush(Color.FromArgb(r, g, b));
Another method is here.

Amcharts SerialChart multiple line graphs different category value member paths (Silverlight)

EDIT I rewrote my question to make it more understandable after the conversation below with Tony (thanks!).
GOAL Render multiple line graphs (let's say 2) in the same chart. The charts have different x/y value pairs. For one x-value, I do not know both y-values.
I am using Silverlight. The classes available for this are SerialChart and LineGraph. The data source for both graphs is the same and is set at the SerialChart level. The name of the property for the x-axis is also defined there for both graphs (CategoryValueMemberPath).
As suggested by the amCharts documentation, we need to create objects that have a property for the category axis (x-axis) and then one property per graph. Let's call them "Graph1" and "Graph2". So the data source looks something like this:
List<MyClass> data = new List<MyClass>()
{
new MyClass() { Category = 0.1, Graph1 = 0.14, Graph2 = ??? }
,new MyClass() { Category = 0.15, Graph1 = ???, Graph2 = 0.05 }
,new MyClass() { Category = 0.2, Graph1 = 0.35, Graph2 = ??? }
,new MyClass() { Category = 0.18, Graph1 = ???, Graph2 = 0.12 }
... and so on ...
}
PROBLEM What am I supposed to do about the "???" values? I do not have the actual value for that graph for that category value.
If I do not set a value, the default value of 0.0 is assumed and it draws a spike to the x-axis. If I set the previously known Graph1/Graph2 value, then it creates a horizontal connection where there is not supposed to be one. I am basically altering the graph which leads to a wrong result.
So how do I solve this? I am getting the feeling that amCharts do not support this scenario.
You need to add two 'value' axes, one in the X direction and one in the Y direction (imagine, like a bubble chart).
// AXES
// X
var xAxis = new AmCharts.ValueAxis();
xAxis.position = "bottom";
xAxis.gridAlpha = 0.1;
xAxis.autoGridCount = true;
chart.addValueAxis(xAxis);
// Y
var yAxis = new AmCharts.ValueAxis();
yAxis.position = "left";
yAxis.gridAlpha = 0.1;
yAxis.autoGridCount = true;
chart.addValueAxis(yAxis);
Merge all your data points into one array with a common X axis field name ('x' in my example) and for points on line 1, add a property of 'line1' with its value, and for points on line 2, add a property of 'line2'.
For example, your data would look like this:
var chartData = [
{x:0.1,line1:0.25},
{x:0.246,line1:0.342},
{x:0.12,line2:0.16},
{x:0.3,line2:0.485}
];
Then add a 'graph' for each line to your chart specifying where to get the value from in the object array.
// GRAPHS
var graph = new AmCharts.AmGraph();
graph.xField = "x";
graph.yField = "line1";
graph.lineAlpha = 1;
graph.lineColor = '#FF9E01';
chart.addGraph(graph);
var graph2 = new AmCharts.AmGraph();
graph2.xField = "x";
graph2.yField = "line2";
graph.lineAlpha = 1;
graph2.lineColor = '#9EFF01';
chart.addGraph(graph2);
I've put all this into a Fiddle for you - http://jsfiddle.net/64EWx/

Resources