ZigZag path onMouseDrag with paper.js - paperjs

Hi im tryign to create a zigzag path using Path.js's onMouseDrag function but getting in to a bit of a muddle here is a sketch
and code
var path
var zigzag
var length
var count
var delta=[]
tool.fixedDistance= 20
function onMouseDown(event){
path= new Path()
path.add(event.point)
zigzag= new Path()
}
function onMouseDrag(event){
event.delta += 90
path.add(event.delta)
delta.push(event.delta)
}
function onMouseUp(event){
length= path.segments.length
zigzag= new Path()
zigzag.add(event.point)
console.log(delta)
delta.forEach(( zig , i) => {
zigzag.add(i % 2 == 0 ? zig + 20 : zig - 20)
})
zigzag.selected= true
}

Based on my previous answer, here is a sketch demonstrating a possible way to do it.
let line;
let zigZag;
function onMouseDown(event) {
line = new Path({
segments: [event.point, event.point],
strokeColor: 'black'
});
zigZag = createZigZagFromLine(line);
}
function onMouseDrag(event) {
line.lastSegment.point = event.point;
if (zigZag) {
zigZag.remove();
}
zigZag = createZigZagFromLine(line);
}
function createZigZagFromLine(line) {
const zigZag = new Path({ selected: true });
const count = 20, length = line.length;
for (let i = 0; i <= count; i++) {
const offset = i / count * length;
const normal = i === 0 || i === count
? new Point(0, 0)
: line.getNormalAt(offset) * 30;
const point = line.getPointAt(offset).add(i % 2 == 0 ? normal
: -normal);
zigZag.add(point);
}
return zigZag;
}

Related

Adding points to Path.Circle first point is at 0,0?

Hello in a for loop whne I add points to a circle the first point is always at 0,0? and not at the beginning of the circle? sketch
var circle= new Path.Circle({
radius: 100,
position: [200,200]
})
splat= new Path.Circle()
splat.fillColor= 'pink'
var count= 40
var length= circle.length
for(var i = 0; i <= count; i++){
var offset= i / count * length
const normal = i === 0 || i === count
? new Point(0, 0)
: circle.getNormalAt(offset) * (Math.random() * 50);
const point = circle.getPointAt(offset).add(i % 2 == 0 ? normal
: -normal);
console.log(point)
splat.add(point)
splat.smooth({ type: 'catmull-rom', factor: 0.5 });
}
splat.closed= true
Thanks in advance
Your path should be created using the generic new Path() constructor and not the specific new Path.Circle() constructor which expects a center and a radius and creates a 0 wide circle at point 0,0 when you're not passing them.
splat= new Path.Circle() => splat= new Path()

Geometry in Plan (Math)

My problem is to know whether or not a point is contained in a polygon (sets of points) on the same surface.
Simple example in my favorite language DART
Point myPoint = new Point(10, 12);
List<Point> myPolygon = [ // The Polygon, for example is simple rect
new Point(2, 7),
new Point(15,7),
new Point(15, 18),
new Point(2, 18)
];
bool pointIsContainedInPolygon(List Polygon){
// .. data processing ...
}
I need to know what is the function: pointIsContainedInPolygon(myPolygon)
I have resumed the code data in the How can I determine whether a 2D Point is within a Polygon? post in dart, here is the result (tested)
bool pnpoly(Point point, List<Point> polygon){
// Step 1: Cut and detail
int nvert = polygon.length;
List<int> vertx = [];
List<int> verty = [];
for(Point vert in polygon){ // Listing x and y pos of all vertices
vertx.add(vert.x);
verty.add(vert.y);
}
// Step 2: Calcul..
bool c = false;
int j = nvert-1;
for (int i = 0; i < nvert; j = i++){
if( ((verty[i]>point.y) != (verty[j]>point.y)) && (point.x < (vertx[j]-vertx[i]) * (point.y-verty[i]) / (verty[j]-verty[i]) + vertx[i]) ){
c = !c;
}
}
return c;
}
Here is my test
List<Point> myPolygon = [ // classic rectangle
new Point(2,2),
new Point(52,2),
new Point(52,41),
new Point(2,41)
];
Point myPoint = new Point(53,40);
print( pnpoly(myPoint, myPolygon) ); // false

LiipImagineBundle / Retina

Is it possible to somehow configure bundle to generate images also for retina display, like #2x?
Or can someone give me an advice how to deal with retina?
Thanks
According to this comment by nahakiole, there are 2 solutions for this:
You can either use the picture element which would provide the syntax
to declare multiple sources for an image.
http://w3c.github.io/html/semantics-embedded-content.html#the-picture-element
The other method which we've tried was, if you can guarantee that the
image exists, to use a modified version of the retina.js which adds
_retina to the filter name and checks if a image with this name exists.
Modified version of retina.js by nahakiole:
/*-----------------------------------------------------------------------------------*/
/* RETINA.JS
/*-----------------------------------------------------------------------------------*/
(function () {
var regex = /(media\/cache\/filter_[A-Z]+)/i //Added this
function t(e) {
this.path = e;
var t = this.path.split("."),
n = t.slice(0, t.length - 1).join("."),
r = t[t.length - 1];
this.at_2x_path = (n + '.' + r).replace(regex, '$1_retina') //Changed that
}
function n(e) {
this.el = e, this.path = new t(this.el.getAttribute("src"));
var n = this;
this.path.check_2x_variant(function (e) {
e && n.swap()
})
}
var e = typeof exports == "undefined" ? window : exports;
e.RetinaImagePath = t, t.confirmed_paths = [], t.prototype.is_external = function () {
return !!this.path.match(/^https?\:/i) && !this.path.match("//" + document.domain)
}, t.prototype.check_2x_variant = function (e) {
var n, r = this;
if (this.is_external()) return e(!1);
if (this.at_2x_path in t.confirmed_paths) return e(!0);
n = new XMLHttpRequest, n.open("HEAD", this.at_2x_path), n.onreadystatechange = function () {
return n.readyState != 4 ? e(!1) : n.status >= 200 && n.status <= 399 ? (t.confirmed_paths.push(r.at_2x_path), e(!0)) : e(!1)
}, n.send()
}, e.RetinaImage = n, n.prototype.swap = function (e) {
function n() {
t.el.complete ? (t.el.setAttribute("width", t.el.offsetWidth), t.el.setAttribute("height", t.el.offsetHeight), t.el.setAttribute("src", e)) : setTimeout(n, 5)
}
typeof e == "undefined" && (e = this.path.at_2x_path);
var t = this;
n()
}, e.devicePixelRatio > 1 && (window.onload = function () {
var e = document.getElementsByTagName("img"),
t = [],
r, i;
for (r = 0; r < e.length; r++) i = e[r], t.push(new n(i))
})
})();

Group an Array of Vectors according to certain Floors in Three.js

I have a list of Vectors which represent points on three different floors in three.js.
I am trying to group these vectors according to the floor they belong to. Is there a good formula to do this? Perhaps find height from on vector or something. Not sure how to go about this. Any help would be appreciated.
Thanks,
Rob
As Wilt said... Can't really help you without more info.
Still, if your floors are even and all stand on the xz plane (in my example), You may indeed check the points' height (position.y) against the floors'.
var container, renderer, scene, camera, controls;
var floors = [];
var points = [], materials = [], heights = [];
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
container = document.createElement('div');
document.body.appendChild(container);
container.appendChild(renderer.domElement);
// scene
scene = new THREE.Scene();
// camera + controls
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 50, 750);
camera.lookAt(scene.position);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
//floors
for(i=0; i<3; i++) {
var planeGeometry = new THREE.BoxGeometry(500, 500, 10, 10);
var planeMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff * Math.random(),
side: THREE.DoubleSide,
transparent: true,
opacity : 0.3,
depthWrite : false //get rid of coplanar glitches wall/floor
});
materials.push(planeMaterial);
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = Math.PI / 2;
//plane.rotation.y = Math.PI / 8; //Uncomment to see this doesn't work if the floors move, i.e. changing rotation/position. If this is what you need, just raycast from point to floor in the animation loop and count how many floors the ray goes through (intersects.length)
plane.position.y = 75*i;
heights.push(plane.position.y);
floors.push(plane);
scene.add(plane);
}
//wall
var height = heights[2];
var planeGeometry = new THREE.BoxGeometry(500, height+100, 10, 10);
var planeMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff * Math.random(),
side: THREE.DoubleSide,
transparent: true,
opacity:0.3,
depthWrite : false //get rid of coplanar glitches wall/floor
});
materials.push(planeMaterial);
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.position.y = heights[1]+45;
plane.position.z = -510/2;
scene.add(plane);
// points
for (i=0; i<200; i++) {
var sphereGeometry = new THREE.SphereGeometry(3, 32, 16);
var sphere = new THREE.Mesh(sphereGeometry);
sphere.position.x = Math.random() * 500 - 250;
sphere.position.y = Math.random() * 300 - 100;
sphere.position.z = Math.random() * 500 - 250;
scene.add(sphere);
points.push(sphere);
}
// events
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize(event) {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function addSpheres() {
//addSpheres
for (i=0;i<200;i++) {
var that = points[i].position.y;
points[i].position.y = ( that < heights[0] ) ? 200 : that - 0.5;
if ( that > heights[0] && that < heights[1] ) points[i].material = materials[0];
if ( that < heights[2] && that > heights[1] ) points[i].material = materials[1];
if ( that > heights[2] ) points[i].material = materials[2];
points[i].material.needsUpdate = true;
}
}
function animate() {
controls.update();
addSpheres();
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>
Now, feel free to "group" these points according to your needs.
Please note that "vectors" are different from "points". Read more about the difference.
Raycasting would be the way to go if you had a more complex scene (moving floors/different planes, points moving in different directions).

How to put a infowindow on polyline in Google Maps v3?

I want to know how to show infowindow on polyline in using Google Maps Api V3? and to appear in the middle of the polyline ?!
Firstly you will need to calculate the middle/center of the polyline. This has been discussed and answered here;
https://stackoverflow.com/a/9090409/787921
Then you will have to open the infowindow;
var infowindow = new google.maps.InfoWindow({
content: "infowindow text content"});
infowindow.setPosition(midLatLng);
infowindow.open(map);
find the middle point and set your custom view .
func showPath(polyStr :String){
polyline?.map = nil
mapView1.reloadInputViews()
pathDraw = GMSPath(fromEncodedPath: polyStr)!
polyline = GMSPolyline(path: pathDraw)
polyline?.strokeWidth = 4.0
polyline?.strokeColor = UIColor.init(red: 247/255.0, green: 55/255.0, blue: 76/255.0, alpha: 1.0)
polyline?.map = mapView1
let poinsCount = pathDraw.count()
let midpoint = pathDraw.coordinate(at: poinsCount)
DispatchQueue.main.async
{
self.addMarkerPin(corrdinate: midCordinate, distance: "10 min")
}
}
func addMarkerPin(corrdinate:CLLocationCoordinate2D, distance: String)
{
let marker = GMSMarker()
marker.position = corrdinate
PathTimeView = PathInfoView.loadFromNib() //here i am load Xib file, you can use your custom view
let DynamicView=PathTimeView
DynamicView.timelbl.text = distance
UIGraphicsBeginImageContextWithOptions(DynamicView.frame.size, false, UIScreen.main.scale)
DynamicView.layer.render(in: UIGraphicsGetCurrentContext()!)
let imageConverted: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
marker.icon = imageConverted
marker.map = self.mapView1
marker.infoWindowAnchor = CGPoint(x: -1900 , y: -2000)
}
First you should got center/middle of polyline and this what works for me
private fun centerPos(points: MutableList<LatLng>): LatLng {
val middleDistance = SphericalUtil.computeLength(points).div(2)
return extrapolate(points, points.first(), middleDistance.toFloat()) ?: points[0]
}
private fun extrapolate(path: List<LatLng>, origin: LatLng, distance: Float): LatLng? {
var extrapolated: LatLng? = null
if (!PolyUtil.isLocationOnPath(
origin,
path,
false,
1.0
)
) { // If the location is not on path non geodesic, 1 meter tolerance
return null
}
var accDistance = 0f
var foundStart = false
val segment: MutableList<LatLng> = ArrayList()
for (i in 0 until path.size - 1) {
val segmentStart = path[i]
val segmentEnd = path[i + 1]
segment.clear()
segment.add(segmentStart)
segment.add(segmentEnd)
var currentDistance = 0.0
if (!foundStart) {
if (PolyUtil.isLocationOnPath(origin, segment, false, 1.0)) {
foundStart = true
currentDistance = SphericalUtil.computeDistanceBetween(origin, segmentEnd)
if (currentDistance > distance) {
val heading = SphericalUtil.computeHeading(origin, segmentEnd)
extrapolated = SphericalUtil.computeOffset(
origin,
(distance - accDistance).toDouble(),
heading
)
break
}
}
} else {
currentDistance = SphericalUtil.computeDistanceBetween(segmentStart, segmentEnd)
if (currentDistance + accDistance > distance) {
val heading = SphericalUtil.computeHeading(segmentStart, segmentEnd)
extrapolated = SphericalUtil.computeOffset(
segmentStart,
(distance - accDistance).toDouble(),
heading
)
break
}
}
accDistance += currentDistance.toFloat()
}
return extrapolated
}
then You can add infoWindow with normal way with your platform at it is differ from each platform

Resources