How to create a custom dashed line separator? - itext

Using DottedLineSeparator class i am able to draw dotted line separator in itext. Similarly is it possible to draw continuous hyphens like '---------------------' as separator in a PdfPCell?
I checked the example here. Is any other solutions available?

The LineSeparator class can be used to draw a solid horizontal line. Either as the equivalent of the <hr> tag in HTML, or as a separator between two parts of text on the same line. The DottedLineSeparator extends the LineSeparator class and draws a dotted line instead of a solid line. You can define the size of the dots by changing the line width and you get a method to define the gap between the dots.
You require a dashed line and it's very easy to create your own LineSeparator implementation. The easiest way to do this, is by extending the DottedLineSeparator class like this:
class CustomDashedLineSeparator extends DottedLineSeparator {
protected float dash = 5;
protected float phase = 2.5f;
public float getDash() {
return dash;
}
public float getPhase() {
return phase;
}
public void setDash(float dash) {
this.dash = dash;
}
public void setPhase(float phase) {
this.phase = phase;
}
public void draw(PdfContentByte canvas, float llx, float lly, float urx, float ury, float y) {
canvas.saveState();
canvas.setLineWidth(lineWidth);
canvas.setLineDash(dash, gap, phase);
drawLine(canvas, llx, urx, y);
canvas.restoreState();
}
}
As you can see, we introduce two extra parameters, a dash value and a phase value. The dash value defines the length of the hyphen. The phase value tells iText where to start (e.g. start with half a hyphen).
Please take a look at the CustomDashedLine example. In this example, I use this custom implementation of the LineSeparator like this:
CustomDashedLineSeparator separator = new CustomDashedLineSeparator();
separator.setDash(10);
separator.setGap(7);
separator.setLineWidth(3);
Chunk linebreak = new Chunk(separator);
document.add(linebreak);
The result is a dashed line with hyphens of 10pt long and 3pt thick, with gaps of 7pt. The first dash is only 7.5pt long because we didn't change the phase value. In our custom implementation, we defined a phase of 2.5pt, which means that we start the hyphen of 10pt at 2.5pt, resulting in a hyphen with length 7.5pt.
You can use this custom LineSeparator in the same way you use the DottedLineSeparator, e.g. as a Chunk in a PdfPCell.

double wPage = doc.PageSize.Width;
double hPage = doc.PageSize.Height;
cb.MoveTo(0,hPage/2);
for (int i = 0; i < wPage; i+=5)
{
cb.LineTo(i, hPage / 2);
i += 5;
cb.MoveTo(i, hPage / 2);
}
this is a solution too :))

Related

Is there any way to know if the lines on the canvas (Path) are overlapping?

I would like to know if there is any logic or function to get a bool when two lines overlap, I tried to do it myself with for cycles of each List<Offset>, however each Offset is not exact, because depending on how you draw it, you put a point and then add the line, something like that is my code to draw :
void _drawFromPointList(Canvas canvas, DrawnShape currentShape) {
final Path path = Path();
final pointList = currentShape.pointList;
/// starts at first point
path.moveTo(
pointList[0].dx,
pointList[0].dy,
);
/// goes through every point of the line, (starts at 1)
for (int f = 1; f < pointList.length; f++) {
path.lineTo(pointList[f].dx, pointList[f].dy);
}
/// draw the line
canvas.drawPath(path, currentShape.paint);
}
}
You can use Path.combine() to achieve that.
Should be something along the lines of:
final intersection = Path.combine(PathOperation.intersect, path1, path2);
final pathsAreIntersecting = !intersection.getBounds().isEmpty;

y component of Vector3 doesn't match

I have this coroutine to calculate the velocity
IEnumerator CalcVelocity()
{
prevPos = transform.position;
yield return new WaitForEndOfFrame();
print(((prevPos - transform.position) / Time.deltaTime));
print(((prevPos - transform.position) / Time.deltaTime).y);
velocity = Mathf.Abs(((prevPos - transform.position) / Time.deltaTime).y);
}
I'm printing out the velocity in all directions and then the y velocity as that's the only I need for my purpose.
However sometimes the serialized Vector3 and the y component don't match - as below they are wildly different. The y value seems to be completely wrong.
(0.0, 0.0, 0.0) // the Vector3 printout
8.488064E-05 // the y
What's gone wrong here?
What's gone wrong here?
Nothing, it's just how unity show things in your log
If you run this
public void Test()
{
var v = new Vector3(0f, 0.00001f, 0f);
var y = v.y;
Debug.Log($"{v}");
Debug.Log($"{y}");
}
You will see this
If you want to see more than 1 decimal, you can use formatters
public void Test()
{
var v = new Vector3(0f, 0.00001f, 0f);
var y = v.y;
Debug.Log($"{v.ToString("F5")}");
Debug.Log($"{y}");
}
N
Nothing is wrong.
The default implementation of Vector3.ToString uses a human readable rounded display (see source code)
public override string ToString()
{
return ToString(null, CultureInfo.InvariantCulture.NumberFormat);
}
public string ToString(string format)
{
return ToString(format, CultureInfo.InvariantCulture.NumberFormat);
}
public string ToString(string format, IFormatProvider formatProvider)
{
if (string.IsNullOrEmpty(format))
format = "F1";
return UnityString.Format("({0}, {1}, {2})", x.ToString(format, formatProvider), y.ToString(format, formatProvider), z.ToString(format, formatProvider));
}
As you can see by default it uses "F1" meaning fixed floating point format rounded to a single decimal.
You can provide any custom format you want like e.g.
print(((prevPos - transform.position) / Time.deltaTime).ToString("G9"));
Where "G" is the general formatter allowing to either print scientific or fixed point presentation depending on which one is more compact.
By chosing G9 it ensures that the float values are printed and then if they would get parsed again would always successfully roundtrip without any data loss.
For more information about available formatting strings see Standard Numeric Format Strings and Custom Format Strings

Unable to draw in processing language when I integrated it with Eclipse

My setup method looks like below, I want to read one location file(City names with x and y co-ordinates) and then I am creating one hash-map of all cities so that I can draw(Will make points) them all on canvas
public void setup(){
background(0);
PFont title = createFont("Georgia", 16);
textFont(title);
text("This is a visualization of A* algorithm", 240, 20);
stroke(255);
line(0,25,800,25);
selectInput("Select a file for Locations:", "locFileSelected");
}
locFileSelected method(locFilePath is a global variable used):
public void locFileSelected(File locFile) {
locFilePath = locFile.toString();
this.readLocFileAndDraw();
}
Now control is transferred to readLocFileAndDraw (Each line in file has space separated 3 words, 1st is city name followed by x and y co-ordinates:
private void readLocFileAndDraw() {
try (Stream<String> lines = Files.lines(Paths.get(locFilePath))) {
for (String line : (Iterable<String>) lines::iterator){
// Last line in file is END, skip it
if(!line.equalsIgnoreCase("END")) {
List<Double> list = new ArrayList<Double>();
String[] arr= line.split(" ");
// adding coordinates into the list
list.add(Double.valueOf(arr[1]));
list.add(Double.valueOf(arr[2]));
// adding the list into the map with key as city name
locationsMap.put(arr[0], list);
}
}
} catch (IOException e) {
e.printStackTrace();
System.exit(0);
}
// Draw cities on map
// Draw graph of all cities
int w=1, h=1;
Set<Entry<String, List<Double>>> locationKeyEntries = locationsMap.entrySet();
for(Entry<String, List<Double>> currEntry: locationKeyEntries) {
String currCity = currEntry.getKey();
List<Double> currLocationList = currEntry.getValue();
int x = currLocationList.get(0).intValue();
int y = currLocationList.get(1).intValue();
stroke(255);
ellipse(x, y, w, h);
if(x>755)
x = x-(8*currCity.length());
if(y>755)
y=y-(8*currCity.length());
text(currCity, x,y);
}
return;
}
I tried to debug it, control is going to ellipse method but nothing is getting drew. Any idea? As far as I understand, I am missing passing reference of PApplet but I don't know how to do it...
Like you've mentioned, you really need to debug your program. Verifying that you're calling the ellipse() function is a great first step, but now you should be asking yourself more questions:
What is the value of x, y, w, and h being passed into the ellipse() function?
What is the value of currEntry in the for loop? What is the value of line when you're reading it in?
What are the fill, stroke, and background colors when you're drawing?
Note that I'm not asking you to tell me the answer to these questions. I'm pointing out these questions because they're what you should be asking yourself when you debug your program.
If you still can't figure it out, I really recommend breaking your problem down into smaller pieces and approaching each of those steps one at a time. For example, can you just show a single circle at a hard-coded point? Then work your way up from there. Can you read a single point in from a file and draw that to the screen? Then read two points. Work your way forward in small incremental steps, and post a MCVE if you get stuck. Good luck.

Unity3d Linerenderer not visible

I am trying to draw a line between two UI GameObjects with Linerenderer. In scene mode everything work fine, but in game mode line is invisible. I tried to change Z position of objects but lines are still invisible. Can anyone help me? Thanks in advance
private LineRenderer lineRenderer;
private float counter;
private float dist;
private Vector3 aPos;
private Vector3 bPos;
public Transform origin;
public Transform destination;
public float lineDrawSpeed = 6f;
// Use this for initialization
void Start()
{
lineRenderer = GetComponent<LineRenderer>();
aPos = new Vector3(origin.position.x, origin.position.y, origin.position.z); // Using these to move the lines back
bPos = new Vector3(destination.position.x, destination.position.y, destination.position.z);
lineRenderer.SetPosition(0, aPos);
lineRenderer.SetWidth(3f, 3f);
dist = Vector3.Distance(origin.position, destination.position);
}
// Update is called once per frame
void Update()
{
if (counter < dist)
{
counter += .1f / lineDrawSpeed;
float x = Mathf.Lerp(0, dist, counter);
Vector3 pointA = aPos;
Vector3 pointB = bPos;
Vector3 pointAloneLine = x * Vector3.Normalize(pointB - pointA) + pointA;
lineRenderer.SetPosition(1, pointAloneLine);
}
}
Unless I'm overlooking some logic error in the code you've posted, I think the problem might be with the material.
Generic debugging help for line renderers:
Try setting the color/material of the line renderer:
lineRenderer.sortingOrder = 1;
lineRenderer.material = new Material (Shader.Find ("Sprites/Default"));
lineRenderer.material.color = Color.red;
If that doesn't work, perhaps you need to specify the number of vertexes manually?
mineLaser.SetVertexCount (2);
Finally, if these both don't work, it might just be a logic error; try setting the transforms for the lineRenderer's position to be some predefined value and see if it shows up.
For this specific question:
Ah, so its on a canvas. Assuming you mean the UI canvas, I believe linerenderer is the wrong tool to use in this situation. Check out this question.
One of the answers there suggests to:
just use a panel filled with any color you want and use Height and Width to set the length and the Width of your line
This is impossible in "Screen Space - Overlay" Canvas mode. In that mode UI overlay draws on top of everything in Scene (including LineRenderer, that actually non UI element).
Try to use "Screen Space - Camera" option for your Canvas and "Use World Space" option for you Line Renderer.
I think you must have forgotten to set sorting layer for the line renderer. As this could only be the possible reason if the line is visible in the scene view and not in the game view.

Resizeable quadratic grid

I would like to display a quadratic GridPane inside a window. The window can have every possible size and normally width and height are not equal. Anyway I would like to display the GridPane as square centered like this:
respectively
Ideally there is a configurable padding around the square. The pictures are taken from a canvas approach, but I want to switch to standard controls. Can anyone give me some hints how to achieve this?
One way to achieve an squared layout for your grid for any resolution of your window is rescaling it to use the maximum size of the window (after some padding), while keeping the squared size.
Instead of a GridPane, a simple Group is more flexible for moving its children, though it requires manual layouting of them.
This simple snippet is based on the JavaFX implementation of the 2048 game you can find here. It uses styleable rectangles to create a grid, and over them the 'tiles' are added. To find out more about styling, layouting or tile movement, go to the refered link.
private static final int NUM_CELLS = 15;
private static final int CELL_SIZE = 50;
private static final int TILE_SIZE = CELL_SIZE-15;
private final static int MARGIN = 20;
#Override
public void start(Stage primaryStage) {
// create background square grid
Group gridGroup = new Group();
IntStream.range(0,NUM_CELLS).boxed().forEach(i->
IntStream.range(0,NUM_CELLS).boxed().forEach(j->{
Rectangle cell = new Rectangle(i * CELL_SIZE, j * CELL_SIZE, CELL_SIZE, CELL_SIZE);
cell.setFill(Color.WHEAT);
cell.setStroke(Color.GREY);
gridGroup.getChildren().add(cell);
})
);
// Add grid to board
Group board = new Group(gridGroup);
// add random tiles to board
IntStream.range(0,NUM_CELLS).boxed().forEach(i->
IntStream.range(0,NUM_CELLS).boxed().forEach(j->{
if(i==j || NUM_CELLS-i-1==j){
Label label = new Label();
label.setMinSize(TILE_SIZE, TILE_SIZE);
label.setPrefSize(TILE_SIZE, TILE_SIZE);
label.setMaxSize(TILE_SIZE, TILE_SIZE);
label.setStyle("-fx-background-color: red; -fx-background-radius: 50");
label.setLayoutX((i+0.5)*CELL_SIZE-TILE_SIZE/2);
label.setLayoutY((j+0.5)*CELL_SIZE-TILE_SIZE/2);
board.getChildren().add(label);
}
})
);
Bounds gameBounds = board.getLayoutBounds();
StackPane root = new StackPane(board);
// Listener to rescale and center the board
ChangeListener<Number> resize = (ov, v, v1) -> {
double scale = Math.min((root.getWidth() - MARGIN) / gameBounds.getWidth(),
(root.getHeight() - MARGIN) / gameBounds.getHeight());
board.setScaleX(scale);
board.setScaleY(scale);
board.setLayoutX((root.getWidth() - gameBounds.getWidth()) / 2d);
board.setLayoutY((root.getHeight() - gameBounds.getHeight()) / 2d);
};
root.widthProperty().addListener(resize);
root.heightProperty().addListener(resize);
Scene scene = new Scene(root);
// Maximum size of window
Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
double factor = Math.min(visualBounds.getWidth() / (gameBounds.getWidth() + MARGIN),
visualBounds.getHeight() / (gameBounds.getHeight() + MARGIN));
primaryStage.setScene(scene);
primaryStage.setWidth((gameBounds.getWidth() + MARGIN) * factor);
primaryStage.setHeight((gameBounds.getHeight() + MARGIN) * factor);
primaryStage.show();
}
And this is how it will look like after some window resizing: